Perché non elencare.BinarySearch () ha sovraccarichi che prendono il confronto oltre a ICOMPARER ?
-
28-10-2019 - |
Domanda
Desidero utilizzare List.BinarySearch()
con un tipo di elemento personalizzato.Il tipo personalizzato non implementa IComparable<T>
;invece ho diverse funzioni Comparison<T>
statiche che chiamo perché in vari punti voglio ordinare l'elenco in base a criteri diversi.Inoltre penso che aggiunga chiarezza poiché il modo in cui stai ordinando può essere descritto dal nome della funzione.Ora voglio fare una ricerca binaria nell'elenco.Volevo utilizzare una delle mie funzioni di confronto, solo per scoprire che List.BinarySearch()
non ha un sovraccarico che accetta Comparison<T>
, solo IComparer<T>
.Cerco di evitare IComparer<T>
perché mi sembra sciocco avere una classe separata solo per confrontare gli oggetti.Perché List.BinarySearch()
non ha sovraccarichi che accettano Comparison<T>
oltre a IComparer<T>
?E c'è un modo per utilizzare le mie funzioni Comparison<T>
esistenti in List.BinarySearch()
?
Soluzione
È molto facile creare un IComparer<T>
da un Comparison<T>
: ecco una classe (leggermente modificata) da MiscUtil che puoi usare:
/// <summary>
/// Utility to build an IComparer implementation from a Comparison delegate,
/// and a static method to do the reverse.
/// </summary>
public class ComparisonComparer<T> : IComparer<T>
{
private readonly Comparison<T> comparison;
public ComparisonComparer(Comparison<T> comparison)
{
if (comparison == null)
{
throw new ArgumentNullException("comparison");
}
this.comparison = comparison;
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}
Potresti anche aggiungere un metodo di estensione a List<T>
per farlo per te:
public static int BinarySearch<T>(this List<T> list, Comparison<T> comparison)
{
return list.BinarySearch(new ComparisonComparer(comparison));
}
Altri suggerimenti
Crea wrapper per Comparison
come questo:
public class ComparisonWrapper<T> : IComparer<T>
{
private Comparison<T> comparison;
public ComparisonWrapper(Comparison<T> comparison)
{
this.comparison = comparison;
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}
Ecco un'estensione della risposta di Jon che accetta un'espressione lambda.
public static class ListExtensions
{
public static int BinarySearch<T>(this List<T> list, T item, Func<T, T, int> compare)
{
return list.BinarySearch(item, new ComparisonComparer<T>(compare));
}
}
public class ComparisonComparer<T> : IComparer<T>
{
private readonly Comparison<T> comparison;
public ComparisonComparer(Func<T, T, int> compare)
{
if (compare == null)
{
throw new ArgumentNullException("comparison");
}
comparison = new Comparison<T>(compare);
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}