Подтвердить что ты не робот

SortedSet <T> и анонимный IComparer <T> в конструкторе не работает

Как анонимные функции работают как аргументы методов, но не в аргументах конструктора?


Если я создаю List<string>, он имеет метод Sort со следующей подписью:

public void Sort(IComparer<T> comparer)

где выполняется следующее:

List<string> list = new List<string>();
list.Sort( (a,b) => a.CompareTo(b) );

SortedSet имеет конструктор с аналогичной сигнатурой:

public SortedSet(IComparer<T> comparer)

но это не удается при использовании анонимной функции в конструкторе. Недопустимо следующее:

SortedSet<string> set = new SortedSet<string>( (a, b) => a.CompareTo(b) );

Создание класса сортировки работает нормально, как ожидалось:

public class MyComparer : IComparer<string>
{
    public int Compare(string a, string b)
    { return a.CompareTo(b); }
}

SortedSet<string> set = new SortedSet<string>( new MyComparer() );
4b9b3361

Ответ 1

Это потому, что конструктор принимает IComparer<T> (интерфейс), а не Comparison<T> (делегат). Anon-methods/lambdas могут поддерживать делегаты, но не (напрямую) интерфейсы. Это довольно легко обернуть, хотя - например:

class FuncComparer<T> : IComparer<T>
{
    private readonly Comparison<T> comparison;
    public FuncComparer(Comparison<T> comparison) {
        this.comparison = comparison;
    }
    public int Compare(T x, T y) {
        return comparison(x, y); }
}

Теперь вы можете использовать:

SortedSet<string> set = new SortedSet<string>(
      new FuncComparer<string>( (a, b) => a.CompareTo(b) ));

Ответ 2

В выпуске .NET Framework 4.5 представлен метод factory Comparer<T>.Create:

var set = new SortedSet<string>(
    Comparer<string>.Create((a, b) => a.CompareTo(b)));

Ответ 3

В вашем случае List.Sort использует эту подпись

public void Sort(Comparison<T> comparison)

но не этот

public void Sort(IComparer<T> comparer)

Ответ 4

Объяснение замечательно, что SortedSet принимает интерфейс, но не является делегатом. (Но Java делает).

Из-за этого ребята .Net предоставляют метод factory для создания такого объекта, поэтому вам не нужно определять для него новый класс.

var set = new SortedSet<string>( 
    Comparer<string>.Create((a, b) => a.CompareTo(b))
);