【问题标题】:IEqualityComparer and Contains methodIEqualityComparer 和 Contains 方法
【发布时间】:2013-01-29 10:21:56
【问题描述】:

我有一个包含这 2 个枚举字段的简单类,我试图在集合中找到该对象的一项 (List<T>),但 Contains 方法无法正常工作

public class Calculator : IEqualityComparer<Calculator>
{
    public DashboardsComputationMode ComputationMode { get; set; }
    public Modes Mode { get; set; }

    public Calculator(DashboardsComputationMode dashboardsComputationMode, Modes mode)
    {
        ComputationMode = dashboardsComputationMode;
        Mode = mode;
    }

    public bool Equals(Calculator x, Calculator y)
    {
        return (x.ComputationMode.Equals(y.ComputationMode) && x.Mode.Equals(y.Mode));
    }

    public int GetHashCode(Calculator obj)
    {
        return obj.ComputationMode.GetHashCode() ^ obj.Mode.GetHashCode();
    }
}

public enum DashboardsComputationMode
{
    Weighted = 0,
    Aggregated = 1,
    PR = 2,
    CurrentValue = 3,
    EquivalentHours = 4,
    AggregatedCorrected = 5,
    PRCorrected = 6
}

public enum Modes
{
    InstantaneousMode = 0,
    DailyMode = 1,
    MonthlyMode = 2,
    YearlyMode = 5,
    Undefined = 4,
}

为什么这个测试不起作用

[TestMethod]
public void TestMethod1()
{
  var list = new List<Calculator>()
  {
    new Calculator(DashboardsComputationMode.PR, Modes.DailyMode),
    new Calculator(DashboardsComputationMode.CurrentValue, Modes.YearlyMode),
    new Calculator(DashboardsComputationMode.PRCorrected, Modes.MonthlyMode)
  };

  var item = new Calculator(DashboardsComputationMode.CurrentValue, Modes.YearlyMode);
  Assert.IsTrue(list[1].Equals(item));
  Assert.IsTrue(list.Contains(item));
}

第一个断言工作正常

Assert.IsTrue(list[1].Equals(item)) 

但第二个没有

Assert.IsTrue(list.Contains(item));

【问题讨论】:

  • 我一直认为 list.Contains 会进行参考检查,因此您必须拥有相同的实例,而不仅仅是匹配。有一个需要 IEqualityComparer 的重载。

标签: c# .net ienumerable


【解决方案1】:

List&lt;T&gt;.Contains 使用默认的相等比较器(EqualityComparer&lt;T&gt;.Default 返回的比较器)确定相等。

这是关于 EqualityComparer&lt;T&gt;.Default 工作原理的 MSDN 说明:

Default 属性检查类型 T 是否实现 System.IEquatable 接口,如果是,则返回一个 EqualityComparer 使用该实现。否则,它 返回一个EqualityComparer,它使用 Object.EqualsObject.GetHashCode由T提供。

换句话说,您的Calculator 类应该实现System.IEquatable不是System.IEqualityComparer!)接口或覆盖Object.EqualsObject.GetHashCode 方法。

【讨论】:

    【解决方案2】:

    您没有在 Equals 和 Contains 中使用 IEqualityComparer&lt;Calculator&gt;EqualityComparer 有不同的意义。我为你更正了代码。

      public class CalculatorComparer : IEqualityComparer<Calculator>
    {
    
        public bool Equals(Calculator x, Calculator y)
        {
            return (x.ComputationMode.Equals(y.ComputationMode) && x.Mode.Equals(y.Mode));
        }
    
        public int GetHashCode(Calculator obj)
        {
            return obj.ComputationMode.GetHashCode() ^ obj.Mode.GetHashCode();
        }
    }
    public class Calculator
    {
        public DashboardsComputationMode ComputationMode { get; set; }
        public Modes Mode { get; set; }
    
        public Calculator(DashboardsComputationMode dashboardsComputationMode, Modes mode)
        {
            ComputationMode = dashboardsComputationMode;
            Mode = mode;
        }
    
    
        public override bool Equals(object obj)
        {
            Calculator y = obj as Calculator;
    
            return (this.ComputationMode.Equals(y.ComputationMode) && this.Mode.Equals(y.Mode));
        }
    }
    
    public enum DashboardsComputationMode
    {
        Weighted = 0,
        Aggregated = 1,
        PR = 2,
        CurrentValue = 3,
        EquivalentHours = 4,
        AggregatedCorrected = 5,
        PRCorrected = 6
    }
    
    public enum Modes
    {
        InstantaneousMode = 0,
        DailyMode = 1,
        MonthlyMode = 2,
        YearlyMode = 5,
        Undefined = 4,
    }
    

    现在两者都应该返回 true。

    【讨论】:

    • 在尝试转换对象obj后需要在calculator.Equals方法中检查null,如果是null则返回false
    • 谢谢,如果我按照你说的写Equals方法就可以了,事实上,实现IEquatable我不需要创建CalculatorComparer
    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2017-06-18
    • 2019-08-15
    • 1970-01-01
    • 2014-12-09
    • 2015-07-03
    • 2019-05-09
    相关资源
    最近更新 更多