Если вам нужно выполнить операции сравнения на основе прогнозируемого ключа данного типа, я считаю, что полезно иметь класс KeyComparer
, который может создавать экземпляр IComparer<TSource>
из делегата Func<TSource, TKey>
. Это особенно хорошо работает с новым синтаксисом кортежей, представленным в C # 7. Вот пример результирующего синтаксиса:
// Create an IComparer<Header> instance based on your combined key.
var comparer = KeyComparer.Create((Header h) => (h.IsRequired, h.Index, h.AvailableDate, h.Key));
List<Header> headers = ...
// Sort the list using the combined key.
headers.Sort(comparer);
// Convert to a dictionary keyed by the combined key.
var dict = headers.ToDictionary(comparer.KeySelector);
А вот пример реализации класса. (Более подробное объяснение см. в моем блоге .)
public static class KeyComparer
{
public static KeyComparer<TSource, TKey> Create<TSource, TKey>(
Func<TSource, TKey> keySelector,
IComparer<TKey> innerComparer = null)
{
return new KeyComparer<TSource, TKey>(keySelector, innerComparer);
}
}
public class KeyComparer<TSource, TKey> : Comparer<TSource>
{
protected internal KeyComparer(
Func<TSource, TKey> keySelector,
IComparer<TKey> innerComparer = null)
{
KeySelector = keySelector ?? throw new ArgumentNullException(nameof(keySelector));
InnerComparer = innerComparer ?? Comparer<TKey>.Default;
}
public Func<TSource, TKey> KeySelector { get; }
public IComparer<TKey> InnerComparer { get; }
public override int Compare(TSource x, TSource y)
{
if (object.ReferenceEquals(x, y))
return 0;
if (x == null)
return -1;
if (y == null)
return 1;
TKey xKey = KeySelector(x);
TKey yKey = KeySelector(y);
return InnerComparer.Compare(xKey, yKey);
}
}