2010-06-28 7 views
17

Wie funktioniert anonyme Funktionen als Argumente für Methoden, aber nicht in Konstruktorargumente?SortedSet <T> und anonymer IComparer <T> im Konstruktor funktioniert nicht


Wenn ich ein List<string> schaffen, hat es eine Sort-Methode mit folgenden Signatur:

public void Sort(IComparer<T> comparer) 

, wo die folgenden Werke:

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

SortedSet einen Konstruktor mit einer ähnlichen Signatur :

public SortedSet(IComparer<T> comparer) 

Dies schlägt jedoch fehl, wenn eine anonyme Funktion im Konstruktor verwendet wird. Das Folgende ist nicht gültig:

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

Erstellen einer Sortierklasse funktioniert wie erwartet fein:

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

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

Antwort

27

Dass es da the constructor eine IComparer<T> (Schnittstelle) akzeptiert, sondern als ein Comparison<T> (Delegierter). Anon-Methoden/Lambdas können Delegaten, aber nicht (direkt) Schnittstellen unterstützen. Es ist ziemlich einfach zu wickeln, wenn - zum Beispiel:

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); } 
} 

Jetzt können Sie verwenden:

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

Danke für die Erklärung und Wrapper-Code. Ich sehe jetzt, dass ich den Vergleich und nicht IComparere on sort. –

0

ich Ihren Fall List.Sort verwendet diese Unterschrift

public void Sort(Comparison<T> comparison) 

aber nicht diese

public void Sort(IComparer<T> comparer) 
18

Das .NET Framework 4.5 re Leasing eingeführt, um die Factory-Methode Comparer<T>.Create:

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

Was ist, wenn ich das Set zwischen Schlüsseln unterscheiden lassen möchte, aber nach Werten sortiert? – shinzou

0

Die Erklärung dafür ist groß, dass SortedSet eine Schnittstelle akzeptiert, aber nicht ein Delegierter (Aber Java tut)..

Aus diesem Grund bieten die .Net-Typen eine Factory-Methode zum Erstellen eines solchen Objekts, sodass Sie keine neue Klasse dafür definieren müssen.

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