Was ist der Unterschied zwischen <out T>
und <T>
? Beispielsweise:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
c#
generics
covariance
Cole Johnson
quelle
quelle
Antworten:
Das
out
Schlüsselwort in Generika wird verwendet, um anzuzeigen, dass der Typ T in der Schnittstelle kovariant ist. Siehe Kovarianz und Kontravarianz für Details.Das klassische Beispiel ist
IEnumerable<out T>
. DaIEnumerable<out T>
es kovariant ist, dürfen Sie Folgendes tun:Die zweite Zeile oben würde fehlschlagen, wenn dies nicht kovariant wäre, obwohl dies logischerweise funktionieren sollte, da die Zeichenfolge vom Objekt abgeleitet ist. Bevor C # und VB.NET (in .NET 4 mit VS 2010) Abweichungen bei generischen Schnittstellen hinzugefügt wurden, war dies ein Fehler bei der Kompilierung.
Nach .NET 4
IEnumerable<T>
wurde kovariant markiert und wurdeIEnumerable<out T>
. DaIEnumerable<out T>
nur die darin enthaltenen Elemente verwendet werden und diese niemals hinzugefügt / geändert werden, ist es sicher, eine aufzählbare Sammlung von Zeichenfolgen als eine aufzählbare Sammlung von Objekten zu behandeln, was bedeutet, dass sie kovariant ist .Dies würde mit einem Typ wie nicht funktionieren
IList<T>
, daIList<T>
es eineAdd
Methode gibt. Angenommen, dies wäre zulässig:Sie könnten dann anrufen:
Dies würde natürlich fehlschlagen -
IList<T>
kann also nicht als kovariant markiert werden.Es gibt übrigens auch eine Option für
in
- die von Dingen wie Vergleichsschnittstellen verwendet wird.IComparer<in T>
funktioniert zum Beispiel umgekehrt. Sie können einen BetonIComparer<Foo>
direkt alsIComparer<Bar>
if-Bar
Unterklasse von verwendenFoo
, da dieIComparer<in T>
Schnittstelle kontravariant ist .quelle
Image
es sich um eine abstrakte Klasse handelt;) Sie könnennew List<object>() { Image.FromFile("test.jpg") };
ohne Probleme arbeiten, oder Sie können es auch tunnew List<object>() { new Bitmap("test.jpg") };
. Das Problem mit Ihrem ist, dassnew Image()
nicht erlaubt ist (Sie können auch nicht tunvar img = new Image();
)IList<object>
ist ein bizarres Beispiel. Wenn Sie möchten,object
brauchen Sie keine Generika.Um sich leicht an die Verwendung von
in
und dasout
Schlüsselwort (auch Kovarianz und Kontravarianz) zu erinnern , können wir die Vererbung als Wrapping darstellen:quelle
Erwägen,
und die Funktionen,
Die Funktion , die akzeptiert
ICovariantSkinned<Fruit>
zu akzeptieren , wird in der LageICovariantSkinned<Fruit>
oderICovariantSkinned<Bananna>
weilICovariantSkinned<T>
eine kovariante Schnittstelle undBanana
ist eine ArtFruit
,Die Funktion, die akzeptiert,
ISkinned<Fruit>
kann nur akzeptierenISkinned<Fruit>
.quelle
"
out T
" bedeutet, dass der TypT
"kovariant" ist. Dies beschränkt sichT
darauf, nur als zurückgegebener (ausgehender) Wert in Methoden der generischen Klasse, Schnittstelle oder Methode angezeigt zu werden. Die Implikation ist, dass Sie den Typ / die Schnittstelle / die Methode in ein Äquivalent mit einem Supertyp von umwandeln könnenT
.ZB
ICovariant<out Dog>
kann gegossen werdenICovariant<Animal>
.quelle
out
VollstreckungenT
nur zurückgegeben werden können, bis ich diese Antwort gelesen habe. Das ganze Konzept macht jetzt mehr Sinn!Von dem Link, den Sie gepostet haben ....
EDIT : Wieder von dem Link, den Sie gepostet haben
quelle