10

我写了一类帐户对象并持有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);
   }
}
4

5 回答 5

13

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

if ((index = AccountList.FindIndex(a => a.name == account.name)) >= 0)
    AccountList[index] = account;

这样您就可以搜索任意字段或字段数量。如果您无权访问源代码Account以添加重载Equals方法,这将特别有用。

于 2013-08-01T21:57:09.567 回答
11

接受的答案没有涵盖的一件事是您应该覆盖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);
    }
}
于 2013-08-01T21:43:47.087 回答
10

您的对象应实现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);
    }
}
于 2013-08-01T20:31:15.177 回答
4

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

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

于 2013-08-01T20:38:51.500 回答
0

您可以为您的类使用自定义谓词,例如:

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);
    }
  }
}

然后你可以按如下方式使用它:

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
}

您甚至可以更改 IndeOfName 类以使用标志在您正在寻找的信息类型之间切换。例如:名称或新信息。

于 2019-01-03T15:37:30.253 回答