2017-06-10 5 views
0

Ich versuche, eine Sortiermethode für eine IList<T>, mit dem folgenden Code zu implementieren:InvalidCastException beim Gießen IList <T> zu IList

public static void Sort<T>(this IList<T> list, Comparison<T> comparison) 
{ 
    ArrayList.Adapter((IList)list).Sort(Comparer<T>.Create(comparison)); 
} 

ich die Methode für eine Liste von Elementen eines bekannten Typs aufrufen und die Bereitstellung dieser Funktionen erzeugt Vergleich:

cardwraplayout.Children.Sort((x, y) => 
{ 
    Card card1 = Cards.FindCardByIconId(x.Id); 
    Card card2 = Cards.FindCardByIconId(x.Id); 
    int result = card1.Rarity.CompareTo(card2.Rarity); 
    if (result == 0) 
    { 
     result = card1.Name.CompareTo(card2.Name); 
    } 
    return result; 
}); 

Wenn ich das obige Verfahren nennen, ein InvalidCastException an dieser Linie auftritt: ArrayList.Adapter((IList)list).Sort(Comparer<T>.Create(comparison));:

System.InvalidCastException: Specified cast is not valid.

Warum kann ich meine IList<T> nicht in IList umwandeln, um meine eigene Sortierfunktion zu implementieren?

Update 1: Versuchte Änderung Comparer<T> zu Comparer<object>, löst immer noch die gleiche Ausnahme aus.

public static void Sort<T>(this IList<T> list, Comparison<object> comparison) 
{ 
    ArrayList.Adapter((IList)list).Sort(Comparer<object>.Create(comparison)); 
} 

Image img1; 
Image img2; 

cardwraplayout.Children.Sort((x,y) => 
{ 
    img1 = (Image)x; 
    img2 = (Image)y; 
    Card card1 = Cards.FindCardByIconId(img1.Id); 
    Card card2 = Cards.FindCardByIconId(img2.Id); 
    int result = card1.Rarity.CompareTo(card2.Rarity); 
    if (result == 0) 
    { 
     result = card1.Name.CompareTo(card2.Name); 
    } 
    return result; 
}); 

Update 2: Erstellen einer Comparer-Klasse wird nicht funktionieren, weil ich mehrere Felder von einer anderen Klasse zugreifen müssen, die mir den folgenden Fehler geben:

An object reference is required for the nonstatic field, method, or property "Cards"

+1

Es gibt keine implizite Umwandlung von "IList" nach "IList ' AFAIK. Die 2 Schnittstellen sind einfach nicht kompatibel. Sie könnten einfach 'list.ToArray(). Sortieren ...' – apokryfos

+1

@apokryfos würde das meine IList ändern oder ein neues Array erstellen? Das erneute Löschen und Wiederauffüllen der Liste ist zu teuer. –

+0

Können Sie die Ausnahme bitte posten? – stybl

Antwort

2

Why can't I cast my IList<T> to IList in order to implement my own sort function?

Es hängt auf dem konkreten Typ der Liste, die Sie erhalten. IList<T> implementiert IList nicht. Konkrete Klassen können wählen, IList<T> und IList zu implementieren, nur IList<T> zu implementieren, nur IList zu implementieren, oder beides zu implementieren. Es gibt keine inhärente Beziehung zwischen den beiden, nur weil sie den Namen teilen.

Zum Beispiel:

Durch Gießen zu IList, sind Sie die Compiler zu sagen: „Es ist in Ordnung, ich weiß mehr als du, ich kenne die Klasse ich wirklich habe IList nicht implementiert.“ Aber die Klasse hat in diesem Fall IList nicht implementiert. Daher der Fehler.

Um eine IList<T> zu sortieren, erstellen Sie etwas, das für IList<T> funktioniert, versuchen Sie nicht, etwas, das für IList gemacht wurde, zu arbeiten. Zum Beispiel könnten Sie alles in eine T[] kopieren, rufen Sie Array.Sort, und kopieren Sie die Ergebnisse zurück. (Das ist tatsächlich effizienter, als was ArrayList.Adapter(...).Sort(...) sowieso getan hätte.) Oder Sie könnten einen der Standardsuchalgorithmen von Hand programmieren.

+0

Das hat funktioniert, aber es ist ineffizient (da die IList ich bin nur lesen - obwohl änderbar, muss ich löschen und manuell wieder den Array-Inhalt) –

+0

@NicodeOry Wenn Sie in der Lage, es zu ändern, ist es sicherlich nicht schreibgeschützt? Ich verstehe nicht, was du damit meinst. – hvd

+0

Ich benutze Xamarin.Forms und modifiziere die Kinder eines Layouts. Offensichtlich ist ihre API so entworfen, dass du 'layout.Children = myArray' nicht machen kannst, aber du kannst' layout.Children.Add (item) 'machen. –