LINQ Distinct avec une seule classe de comparaison (et interface)
-
14-10-2019 - |
Question
J'ai plusieurs classes dans mon application, qui ont toutes une propriété Name
que je veux utiliser comme ma base de comparaison (Distinct()
, etc.). Depuis que je vais toujours être comparer le Name
, je décide d'extraire une interface, ISomeComparedStuff
, qui a simplement une propery de Name
que toutes mes autres classes à mettre en œuvre. Je mis en place une classe de comparaison en tant que tel:
public class MyComparer : IEqualityComparer<ISomeComparedStuff>
{
public bool Equals(ISomeComparedStuff x, ISomeComparedStuff y)
{
return x.Name == y.Name;
}
public int GetHashCode(ISomeComparedStuff obj)
{
return obj.Name.GetHashCode();
}
}
Le seul problème est lorsque je tente de le code contre:
public class SomeStuff : ISomeComparedStuff
{
...
}
public class SomeMoreStuff : ISomeComparedStuff
{
...
}
var someStuff = GetSomeStuff().Distinct(new MyComparer);
var someMoreStuff = GetSomeMoreStuff().Distinct(new MyComparer);
Je reçois une erreur de moulage (SomeStuff
à ISomeComparedStuff
). Est-il possible de le faire, donc je besoin d'un seul comparer classe, sinon je dois créer un pour chacun de mes cours (même si je vais toujours comparer le Name
)?
Note: Je comprends cette question "titre" a besoin d'aide. Toute suggestion serait grande.
La solution
Je ne sais pas si cela est une bonne solution ou non, mais que diriez-vous faire MyComparer une classe générique?
public class MyComparer<T> : IEqualityComparer<T>
where T: ISomeComparedStuff
{
public bool Equals(T x, T y)
{
return x.Name == y.Name;
}
public int GetHashCode(T obj)
{
return obj.Name.GetHashCode();
}
}
Le seul inconvénient est que vous devez créer un nouveau version appropriée:
var someStuff = GetSomeStuff().Distinct(new MyComparer<SomeStuff>());
var someMoreStuff = GetSomeMoreStuff().Distinct(new MyComparer<SomeMoreStuff>());
L'expansion un peu, vous pouvez également faire une nouvelle méthode d'extension comme ceci:
public static IEnumerable<T> DistinctByName<T>(this IEnumerable<T> values)
where T: ISomeComparedStuff
{
return values.Distinct(new MyComparer<T>());
}
Autres conseils
Peut-être quelque chose comme:
var someStuff = GetSomeStuff().Cast<ISomeComparedStuff>().Distinct(new MyComparer);
Ou utilisez le IEqualityComparer
non générique.