Метод IEqualityComparer и Содержит

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

public class Calculator : IEqualityComparer
{
    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()
  {
    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));
15
nl ja de
Я всегда предполагал, что list.Contains выполняет контрольную проверку, поэтому вы должны иметь один и тот же экземпляр, а не только совпадение. Существует перегрузка, которая будет принимать IEqualityComparer.
добавлено автор Jon Egerton, источник

2 ответы

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

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

Свойство Default проверяет, реализует ли тип T    System.IEquatable и, если это так, возвращает    EqualityComparer , который использует эту реализацию. В противном случае   возвращает EqualityComparer , в котором используются переопределения    Object.Equals и Object.GetHashCode , предоставленный T.

Другими словами, ваш класс Calculator должен либо реализовать System.IEquatable ( не интерфейс . !) или переопределить Object.Equals и Object.GetHashCode методы.

Благодаря !! который отлично работает с IEquatable
добавлено автор Pablo Rodríguez, источник

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

  public class CalculatorComparer : IEqualityComparer
{

    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.

5
добавлено
@RobH вы правы. Мне этого не хватает. я добавлю его.
добавлено автор D J, источник
Вам нужно проверить значение null в методе calculator.Equals после попытки передать объект obj, если это null , а затем вернуть false .
добавлено автор RobH, источник
Спасибо, он работает, если я пишу метод Equals, как вы говорите, на самом деле, при реализации IEquatable мне не нужно создавать CalculatorComparer
добавлено автор Pablo Rodríguez, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot