SortedSet<T>和匿名IComparer<T>在构造函数中无法正常工作。

20
为什么匿名函数可以作为方法参数,但无法在构造函数的参数中使用?
如果我创建一个 `List`,它具有以下签名的 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() );
4个回答

36

.NET Framework 4.5发布引入了工厂方法Comparer<T>.Create

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

1
如果我想让集合根据键区分,但按值排序怎么办? - shinzou

33
那是因为构造函数接受一个IComparer<T>(接口),而不是Comparison<T>(委托)。匿名方法/lambda可以支持委托,但不能(直接)支持接口。不过包装起来很容易 - 例如:
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) ));

感谢您的解释和包装器代码。我现在明白了,我在排序时使用的是Comparison<T>而不是IComparer<T>。 - Mikael Svenson

6

SortedSet接受接口而不是委托(但Java可以)的解释很好。

因此,.Net提供了一个工厂方法来创建这样的对象,所以您不需要为此定义一个新类。

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

0

在您的情况下,List.Sort使用此签名

public void Sort(Comparison<T> comparison)

但不包括这个

public void Sort(IComparer<T> comparer)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接