【问题标题】:Intersect doesn't work between Lists交叉在列表之间不起作用
【发布时间】:2017-03-30 09:48:49
【问题描述】:

我有一个奇怪的问题。
我使用 Visual Studio,并且正在使用 C# 开发一个项目。
我有两个自定义类“Attr”和“FD”,我使用包含它们的对象的列表,例如

List<Attr> attrList = new List<Attr>();
List<FD> fdList = new List<FD>(); 

所以当我试图找到两个列表的交集时,结果不是我所期望的。为了使它更简单,我尝试相交相似的对象,结果又是错误的。出了什么问题?

这是fd。它是 FD 类的对象。
这是 ff 也是 FD 类的对象。

如您所见,这些对象包含完全相同的值。
GetLeft() 方法返回一个包含 Attr 类对象的列表。

所以当我试图找到这两个列表(fd.GetLeft()ff.GetLeft() )之间的交集时,结果什么都没有(应该是一个包含 Attr 对象“A”的列表)。

我错过了什么?

附:这些屏幕截图来自 Visual Studio 中的调试模式。

【问题讨论】:

标签: c# visual-studio equality


【解决方案1】:

为了使用Intersect,我建议实现IEqualityComparer&lt;T&gt;,类似这样:

public class FD
{
    public string Name { get; set; }
}

 static void Main()
    {
        List<FD> fdList1 = new List<FD>();
        fdList1.Add(new FD { Name = "a" });

        List<FD> fdList2 = new List<FD>();
        fdList2.Add(new FD { Name = "a" });

       IEnumerable<FD> fd = fdList1.Intersect<FD>(fdList2, new ComparerFd()).ToList();
    }

CamparerFd 应该是这样的:

public class ComparerFd : IEqualityComparer<FD>
{

    public bool Equals(FD x, FD y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(FD obj)
    {
        if(obj == null) return 0;
        
        return obj.Name.GetHashCode();//Or whatever way to get hash code
    }
}

【讨论】:

  • 您对GetHashCode 的实现是错误的,因为仅返回一个随机数不会为相等的对象返回相同的哈希码。因此,Intersect-方法仍然无法工作,如果它使用哈希码进行快速比较(我很确定它确实如此)。一般来说,如果没有正确实现GetHashCode,最好至少返回一个常量值——这样,一切都会正常工作,并且“只是”会变慢......在这种特定情况下,只需返回this.Name.GetHashCode()。跨度>
  • 非常感谢你们! @蒂米特里。问题解决了!
  • this.NameComparerFd 类中不存在。我想你的意思是return obj.Name.GetHashCode();。我已经使用了这种方法并且它有效。另请注意,您应该检查并处理 null:return obj.Name == null ? 0 : obj.Name.GetHashCode();
  • @SleekPanther 感谢您的注释,已在答案中更新:)
【解决方案2】:

如果您创建了自己的类,并且没有覆盖该类中的Equals-方法,则Intersect-方法将只比较对象的引用,而不是属性。

参加以下非常简单的课程:

class MyClass
{
  int Value { get; set; }

  public MyClass(int value)
  {
    this.Value = value;
  }
}

现在,创建两个列表,两个列表都包含一个对象。对象的属性相同,但实例不同:

  var list1 = new List<MyClass>
  {
    new MyClass(5)
  };

  var list2 = new List<MyClass>
  {
    new MyClass(5)
  };

所以会发生以下情况:

  list1[0].Equals(list2[0]); // false
  list1.Intersect(list2); // No matches

如果您希望这些方法比较您的 MyClass-objects 的属性,请实现 IEqualityComparer&lt;MyClass&gt;,例如将类签名更改为:

class MyClass : IEqualityComparer<MyClass>
{
  ..
}

或者,您可以直接覆盖EqualsGetHashCode,因为这些方法将被默认调用为IEqualityComparer

请参阅this answer,了解如何正确覆盖EqualsGetHashCode

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 2020-01-31
    • 2015-09-30
    相关资源
    最近更新 更多