【问题标题】:Compare by reference?参考比较?
【发布时间】:2012-02-14 01:17:54
【问题描述】:

使用 System.Collections.Generic 中的 List 类时,Contains 或 IndexOf 等方法将使用从 IEquatable 实现的 Equals 方法或 Object 类提供的重写 Equals 方法来比较传递的引用的对象。如果 Object.Equals 没有被覆盖,它会检查传入的引用是否指向与自身相同的对象。

我的问题是:如果 Equals 被覆盖,是否有办法通过引用比较 List? 下面的代码将从列表中删除该项目:

class Program
{
    static void Main(string[] args)
    {    
        var s1 = new SomeClass() { A = 5 };
        var s2 = new SomeClass() { A = 5 };
        var list = new List<SomeClass>();
        list.Add(s1);
        list.Remove(s2); // s1 will get removed, even though s2 has been 
                         // passed, because s1's Equals method will return true.

    }
}

class SomeClass
{
    public int A { get; set; }

    public override bool Equals(object obj)
    {
        SomeClass s = obj as SomeClass;
        if (s == null)
        {
            return false;
        }
        else
        {
            return s.A == this.A;
        }
    }   
}

假设我无法删除 SomeClass 的 Equals 实现,有没有办法让 List 按引用而不是值进行比较?

【问题讨论】:

    标签: c# list reference equals


    【解决方案1】:

    您可以使用List.RemoveAll 并在您的谓词中将项目与Object.ReferenceEquals 进行比较。

    list.RemoveAll(item => object.ReferenceEquals(item, s2));
    

    从 Visual Studio 2010 Express 调试时,代码确实成功删除了 1 项。

    【讨论】:

      【解决方案2】:

      Austin 的解决方案既简单又有效。但这里也有两种通用的扩展方法:

      items.RemoveAllByReference(item);
      
      public static void RemoveAllByReference<T>(this List<T> list, T item)
      {
          list.RemoveAll(x=> object.ReferenceEquals(x, item));
      }
      
      public static bool RemoveFirstByReference<T>(this List<T> list, T item)
      {
          var index = -1;
          for(int i = 0; i< list.Count; i++)
              if(object.ReferenceEquals(list[i], item))
              {
                  index = i;
                  break;
              }
          if(index == -1)
              return false;
      
          list.RemoveAt(index);
          return true;
      }
      

      【讨论】:

      • 有趣,但为什么这更优化 - 这不类似于谓词在内部的作用吗?就想知道你的推理...
      • 如果该项目在列表中出现 n 次怎么办?
      • Austin 的方法总是检查所有元素。当它找到一个时,它会打破循环。但是现在当我想到它时,搜索整个列表并删除列表中同一项目的所有实例可能更正确......所以这取决于你想要什么。但是,如果您在多个地方使用扩展方法,它仍然是一个优势。
      • @Austin,是的,你是对的,这个名字有误导性,我改了名字。两种扩展方法,现在按照它说的做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-28
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 2015-07-04
      • 1970-01-01
      相关资源
      最近更新 更多