web-dev-qa-db-fra.com

IEqualityComparer et Contains, méthode

J'ai cette classe simple avec ces 2 champs enum, j'essaie de trouver un élément de cet objet dans une collection (List<T>) mais la méthode Contains ne fonctionne pas correctement

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

Pourquoi ce test ne fonctionne-t-il pas?

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

La première affirmation fonctionne bien

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

mais pas le second

Assert.IsTrue(list.Contains(item));
17
Pablo Rodríguez

List<T>.Contains détermine l'égalité en utilisant le comparateur d'égalité par défaut (celui renvoyé par le EqualityComparer<T>.Default ).

Voici l'explication MSDN sur la façon dont EqualityComparer<T>.Default fonctionne:

La propriété Default vérifie si le type T implémente l'interface System.IEquatable et, si tel est le cas, renvoie un EqualityComparer qui utilise cette implémentation. Sinon, il retourne un EqualityComparer qui utilise les substitutions de Object.Equals et Object.GetHashCode fournies par T.

En d'autres termes, votre classe Calculator doit implémenter la System.IEquatable ( pas la System.IEqualityComparer!) ou remplacez les méthodes Object.Equals et Object.GetHashCode .

23
Nikolay Khil

Vous n'utilisez pas IEqualityComparer<Calculator> dans Égale et contient les deux. EqualityComparer a une signification différente. J'ai corrigé le code pour toi.

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

Maintenant, les deux devraient retourner vrai.

5
D J