Linq distinti con una sola classe di confronto (e l'interfaccia)
-
14-10-2019 - |
Domanda
Ho diverse classi nella mia richiesta, che hanno tutti una proprietà Name
che voglio usare come la mia base per il confronto (Distinct()
, etc.). Dal momento che sto andando sempre essere il confronto su Name
, ho deciso di estrarre un'interfaccia, ISomeComparedStuff
, che ha semplicemente un propery Name
che tutte le mie altre classi implementano. Ho creato una classe di confronto in quanto tale:
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();
}
}
L'unico problema è quando provo a codice contro di esso:
public class SomeStuff : ISomeComparedStuff
{
...
}
public class SomeMoreStuff : ISomeComparedStuff
{
...
}
var someStuff = GetSomeStuff().Distinct(new MyComparer);
var someMoreStuff = GetSomeMoreStuff().Distinct(new MyComparer);
sto ottenendo un errore di cast (SomeStuff
a ISomeComparedStuff
). C'è qualche modo per fare questo quindi ho solo bisogno di un confronto di classe, altrimenti avrei dovuto crearne uno per ogni una delle mie classi (anche se io sono sempre andando a confrontare il Name
)?
Nota: ho capito questa domanda "titolo" ha bisogno di aiuto. Qualsiasi suggerimento sarebbe grande.
Soluzione
Non sono sicuro se questa è una soluzione buona o no, ma come di fare MyComparer una classe generica?
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();
}
}
Unico inconveniente è che devi nuova di un versione appropriata:
var someStuff = GetSomeStuff().Distinct(new MyComparer<SomeStuff>());
var someMoreStuff = GetSomeMoreStuff().Distinct(new MyComparer<SomeMoreStuff>());
L'espansione un po ', si potrebbe anche fare un nuovo metodo di estensione in questo modo:
public static IEnumerable<T> DistinctByName<T>(this IEnumerable<T> values)
where T: ISomeComparedStuff
{
return values.Distinct(new MyComparer<T>());
}
Altri suggerimenti
Forse qualcosa di simile:
var someStuff = GetSomeStuff().Cast<ISomeComparedStuff>().Distinct(new MyComparer);
o utilizzare il IEqualityComparer
non generico.