List <T> .IndexOf()如何执行自定义对象的比较?

bli*_*izz 6 .net c# generics collections

我编写了一类帐户对象并保留了List<T>这些帐户对象的静态.我的程序循环遍历列表中的每个帐户,对帐户执行一些操作,然后在到达列表末尾时在顶部重置.

我的问题是,在我的程序完成后,我需要能够将帐户重新插入列表中,并添加了一些更新的信息.我是否可以按照下面的说明执行此操作,使用IndexOf()函数检查静态列表中的对象,还是因为我向其添加数据而失败?我不明白它比较哪些字段以查看两个对象是否相同.

注意:列表中不允许重复,因此不存在更新错误项目的风险

public class Account
{
   public string name;
   public string password;
   public string newInfo;
}

public static class Resources
{
   private static List<Account> AccountList = new List<Account>();
   private static int currentAccountIndex = 0;

   public static Account GetNextAccount()
   {
      if (currentAccountIndex > AccountList.Count)
         currentAccountIndex = 0;
      return AccountList[currentAccountIndex++];
   }

   public static void UpdateAccount(Account account)
   {
      int index;
      if ((index = AccountList.IndexOf(account)) >= 0)
         AccountList[index] = account;
   }
}

public class Program
{
   public void PerformWork()
   {
      Account account = Resources.GetNextAccount();
      // Do some work
      account.newInfo = "foo";
      Resources.UpdateAccount(account);
   }
}
Run Code Online (Sandbox Code Playgroud)

key*_*rdP 9

您的对象应该实现IEquatable接口并覆盖该Equals方法.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您甚至不必让它实现“IEquatable&lt;T&gt;”。只需重写 `Equals(object)` 和 `GetHashCode` 就可以了。此外,在非密封类上实现“IEquatable”也存在危险。请参阅http://blog.mischel.com/2013/01/05/inheritance-and-iequatable-do-not-mix/ (2认同)

Jim*_*hel 9

另一种选择是使用List.FindIndex,并传递谓词.那是:

if ((index = AccountList.FindIndex(a => a.name == account.name)) >= 0)
    AccountList[index] = account;
Run Code Online (Sandbox Code Playgroud)

这样,您可以搜索任意字段或字段数.如果您无权访问用于Account添加重载Equals方法的源代码,则此功能尤其有用.


Jus*_*ner 5

如果您的类正确实现了IEquatable<T>,那么IndexOf()将使用您的Equals()方法来测试相等性。

否则,IndexOf()将使用引用相等。


Sco*_*ain 5

有一件事接受的答案没盖你应该重写Equals(object),并GetHashCode()IEquatable<T>正确的工作。这是完整的实现(基于keyboardP的答案

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);
    }
}
Run Code Online (Sandbox Code Playgroud)