I wrote a class of account objects and hold a static List
of those account objects. My program loops through each account in the list, performing some
One thing the accepted answer did not cover is you are supposed to override Equals(object)
and GetHashCode()
for IEquatable<T>
to work correctly. Here is the full implementation (based off of keyboardP's answer)
public class Account : IEquatable<Account>
{
public string name;
public string password;
public string newInfo;
private readonly StringComparer comparer = StringComparer.OrdinalIgnoreCase;
public override bool Equals(object other)
{
//This casts the object to null if it is not a Account and calls the other Equals implementation.
return this.Equals(other as Account);
}
public override int GetHashCode()
{
return comparer.GetHashCode(this.newInfo)
}
public bool Equals(Account other)
{
//Choose what you want to consider as "equal" between Account objects
//for example, assuming newInfo is what you want to consider a match
//(regardless of case)
if (other == null)
return false;
return comparer.Equals(this.newInfo, other.newInfo);
}
}
If your class properly implements IEquatable<T>, then IndexOf()
will use your Equals()
method to test for equality.
Otherwise, IndexOf()
will use reference equality.
Your object should implement the IEquatable interface and override the Equals
method.
public class Account : IEquatable<Account>
{
public string name;
public string password;
public string newInfo;
public bool Equals(Account other)
{
//Choose what you want to consider as "equal" between Account objects
//for example, assuming newInfo is what you want to consider a match
//(regardless of case)
if (other == null)
return false;
return String.Equals(this.newInfo, other.newInfo,
StringComparison.OrdinalIgnoreCase);
}
}
You can use a custom Predicate for your class, such as:
public class Account
{
public string name;
public string password;
public string newInfo;
public class IndexOfName
{
private string _match = "";
public IndexOfName()
{
}
public Predicate<Account> Match(string match)
{
this._match = match;
return IsMatch;
}
private bool IsMatch(Account matchTo)
{
if (matchTo == null)
{
return false;
}
return matchTo.Equals(this._match);
}
}
}
Then you can use it as follow:
Account.IndexOf indexOf = new Account.IndexOf();
int index;
if ((index = AccountList.FindIndex(indexOf.Match("john"))) > 0)
{
// do something with John
}
if ((index = AccountList.FindIndex(indexOf.Match("jane"))) > 0)
{
// do something with Jane
}
You could even change the IndeOfName class to use a flag to switch between the type of info you are looking for. Ex: name or newInfo.
Another option is to use List.FindIndex, and pass a predicate. That is:
if ((index = AccountList.FindIndex(a => a.name == account.name)) >= 0)
AccountList[index] = account;
That way you can search on any arbitrary field or number of fields. This is especially useful if you don't have access to the source code for Account
to add an overloaded Equals
method.