2013-02-22 24 views
8

Ich kann implizit einen Int zu einem IComparable Cast. Ich kann auch eine Liste oder ein Array auf IEnumerable umwandeln.Liste <int> zu IEnumerable <IComparable>

Aber warum kann ich eine Liste nicht implizit auf einen IEnumerable umwandeln?

Ich habe dies mit dem .net Framework 4.5 und Visual Studio 2012 Ultimate getestet.

-Code zu testen:

IComparable test1; 
int t1 = 5; 
test1 = t1; //OK 

IEnumerable<int> test2; 
List<int> t2 = new List<int>(); 
int[] t3 = new int[] { 5, 6 }; 
test2 = t2; //OK 
test2 = t3; //OK 

TabAlignment[] test; 

IEnumerable<IComparable> test3; 
test3 = t2; //error Cannot implicitly convert type 'System.Collections.Generic.List<int>' to 'System.Collections.Generic.IEnumerable<System.IComparable>'. An explicit conversion exists (are you missing a cast?) 

Antwort

12

Allgemein Varianz gilt nicht Typen Wert, im Grunde. So, während Sie können

Sie bräuchten um jeden Wert boxen:

IEnumerable<IComparable> test3 = t2.Cast<IComparable>(); 

Während also diese gültig ist, weil string ein Referenztyp ist:

List<string> strings = new List<string>(); 
IEnumerable<IComparable> comparables = strings; 

... das Äquivalent funktioniert nicht für List<int>, und Sie müssen boxen, wie Sie gehen.

+0

tun zu haben mit meinem durch Ihre Antwort und im Vergleich zu lesen (und dann getestet im Code), merke ich, dass mein Fehler in diesem Fall falsch ist, da es sich um Konvertierungen von Liste -> Liste statt Liste -> IEnumerable handelt, aber ich bin verwirrt, warum das einen Unterschied macht. Können Sie erklären? –

+0

@ JonEgerton: Ich vermute, dass Sie generische Typ Argumente in diesem Kommentar, aber ich kann sie nicht sehen. Versuchen Sie es noch einmal, indem Sie die Code-bezogenen Bits mit Backticks abgleichen. –

+1

@JonEgerton: Okay, lesen Sie Ihre Antwort, dann Ihren Kommentar noch einmal ... - es ist, weil 'List ' ist nicht kovariant in 'T', aber' IEnuemrable 'ist (wie von .NET 4). Klassen können niemals Varianten sein. Suche nach "Generic Varianz" auf MSDN für weitere Details :) –

2

Es ist eine gemeinsame Verwirrung mit Listen von Generika, aber wenn man es im Grunde verallgemeinern macht es mehr Sinn:

diese Einstellung vor:

public interface IA{ 
} 

public class A : IA{ 
} 

var listA = new List<A>(); 

Die folgende Zeile nicht funktionieren würde:

List<IA> listI = ListA; 

Im Wesentlichen ist dies, weil, obwohl A : IA, List<I> does not : List<A> - sie sind völlig separate Typen.

Sie die Besetzung leicht genug tun können, obwohl die Cast Methode:

listI = ListA.Cast<IA>(); 

in Ihrem Fall So könnte man

test3 = t2.Cast<IComparable>();