158 votes

LINQ Select Distinct avec les types anonymes

J'ai donc une collection d'objets. Le type exact n'est pas important. Je veux en extraire toutes les paires uniques d'une paire de propriétés particulières, de la manière suivante :

myObjectCollection.Select(item=>new
                                {
                                     Alpha = item.propOne,
                                     Bravo = item.propTwo
                                }
                 ).Distinct();

Ma question est donc la suivante : dans ce cas, Distinct utilisera-t-il les égalités d'objets par défaut (ce qui me sera inutile, puisque chaque objet est nouveau) ou peut-on lui demander d'effectuer des égalités différentes (dans ce cas, valeurs égales d'Alpha et de Bravo => instances égales) ? Existe-t-il un autre moyen d'obtenir ce résultat, si cela ne fonctionne pas ?

0 votes

S'agit-il de LINQ-to-Objects ou de LINQ-to-SQL ? S'il s'agit uniquement d'objets, vous n'avez probablement pas de chance. Cependant, s'il s'agit de L2S, cela peut fonctionner, car le DISTINCT serait transmis à l'instruction SQL.

0 votes

0voto

ern Points 1150

Si Alpha y Bravo héritent toutes deux d'une classe commune, vous pourrez imposer le contrôle de l'égalité dans la classe parente en mettant en œuvre la méthode suivante IEquatable<T> .

Par exemple :

public class CommonClass : IEquatable<CommonClass>
{
    // needed for Distinct()
    public override int GetHashCode() 
    {
        return base.GetHashCode();
    }

    public bool Equals(CommonClass other)
    {
        if (other == null) return false;
        return [equality test];
    }
}

0voto

Modather Sadik Points 9

J'ai eu le même problème et j'ai trouvé une solution. Vous devez implémenter l'interface IEquatable ou simplement surcharger les méthodes (Equals & GetHashCode). Mais ce n'est pas le problème, le problème vient de la méthode GetHashCode. Vous ne devez pas retourner le code de hachage de l'objet de votre classe mais vous devez retourner le hachage de la propriété que vous voulez comparer comme ça.

public override bool Equals(object obj)
    {
        Person p = obj as Person;
        if ( obj == null )
            return false;
        if ( object.ReferenceEquals( p , this ) )
            return true;
        if ( p.Age == this.Age && p.Name == this.Name && p.IsEgyptian == this.IsEgyptian )
            return true;
        return false;
        //return base.Equals( obj );
    }
    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }

Comme vous le voyez, j'ai une classe appelée person avec 3 propriétés (Name, Age, IsEgyptian "Because I am"). Dans le GetHashCode, j'ai renvoyé le hash de la propriété Name et non l'objet Person.

Essayez-le et il fonctionnera ISA. Merci, Modather Sadik

0voto

Pour qu'il fonctionne en VB.NET, vous devez spécifier l'adresse de l'utilisateur. Key avant chaque propriété du type anonyme, comme ceci :

myObjectCollection.Select(Function(item) New With
{
    Key .Alpha = item.propOne,
    Key .Bravo = item.propTwo
}).Distinct()

J'avais du mal avec cela, je pensais que VB.NET ne supportait pas ce type de fonctionnalité, mais en fait si.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X