Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEqualityComparer and Contains method

I have this simple class with those 2 enum fields, I'm trying to find one item of this object in a collection (List<T>) but the Contains methods doesn't works correctly

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,
}

Why could be that this test doesn't works

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

The first assert works fine

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

but the second doesn't

Assert.IsTrue(list.Contains(item));
like image 669
Pablo Rodríguez Avatar asked Jan 29 '13 10:01

Pablo Rodríguez


People also ask

What is IEqualityComparer C#?

IEqualityComparer<T> is a generic . NET interface that allows implementing customized equality comparison for collections. Creating a comparer class for your type is an alternative to creating Equals() and GetHashCode() methods for the type.


2 Answers

List<T>.Contains determines equality by using the default equality comparer (the one returned by the EqualityComparer<T>.Default).

Here's the MSDN explanation on how EqualityComparer<T>.Default works:

The Default property checks whether type T implements the System.IEquatable interface and, if so, returns an EqualityComparer that uses that implementation. Otherwise, it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

In other words, your Calculator class should either implement the System.IEquatable (not the System.IEqualityComparer!) interface or override the Object.Equals and Object.GetHashCode methods.

like image 93
Nikolay Khil Avatar answered Oct 07 '22 05:10

Nikolay Khil


You are not using IEqualityComparer<Calculator> in Equals and Contains both. EqualityComparer has a different significance. I corrected the code for you.

  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,
}

Now both should return true.

like image 31
D J Avatar answered Oct 07 '22 04:10

D J