Was ist der Unterschied zwischen <out T>
und <T>
? Beispielsweise:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
Was ist der Unterschied zwischen <out T>
und <T>
? Beispielsweise:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
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>
. Da IEnumerable<out T>
es kovariant ist, dürfen Sie Folgendes tun:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
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 wurde IEnumerable<out T>
. Da IEnumerable<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>
, da IList<T>
es eine Add
Methode gibt. Angenommen, dies wäre zulässig:
IList<string> strings = new List<string>();
IList<object> objects = strings; // NOTE: Fails at compile time
Sie könnten dann anrufen:
objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
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 Beton IComparer<Foo>
direkt als IComparer<Bar>
if- Bar
Unterklasse von verwenden Foo
, da die IComparer<in T>
Schnittstelle kontravariant ist .
Image
es sich um eine abstrakte Klasse handelt;) Sie können new List<object>() { Image.FromFile("test.jpg") };
ohne Probleme arbeiten, oder Sie können es auch tun new List<object>() { new Bitmap("test.jpg") };
. Das Problem mit Ihrem ist, dass new Image()
nicht erlaubt ist (Sie können auch nicht tun var 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 das out
Schlüsselwort (auch Kovarianz und Kontravarianz) zu erinnern , können wir die Vererbung als Wrapping darstellen:
String : Object
Bar : Foo
Erwägen,
class Fruit {}
class Banana : Fruit {}
interface ICovariantSkinned<out T> {}
interface ISkinned<T> {}
und die Funktionen,
void Peel(ISkinned<Fruit> skinned) { }
void Peel(ICovariantSkinned<Fruit> skinned) { }
Die Funktion , die akzeptiert ICovariantSkinned<Fruit>
zu akzeptieren , wird in der Lage ICovariantSkinned<Fruit>
oder ICovariantSkinned<Bananna>
weil ICovariantSkinned<T>
eine kovariante Schnittstelle und Banana
ist eine Art Fruit
,
Die Funktion, die akzeptiert, ISkinned<Fruit>
kann nur akzeptieren ISkinned<Fruit>
.
" out T
" bedeutet, dass der Typ T
"kovariant" ist. Dies beschränkt sich T
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önnen T
.
ZB ICovariant<out Dog>
kann gegossen werden ICovariant<Animal>
.
out
Vollstreckungen T
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 ....
Bei generischen Typparametern gibt das Schlüsselwort out an, dass der Typparameter kovariant ist .
EDIT : Wieder von dem Link, den Sie gepostet haben
Weitere Informationen finden Sie unter Kovarianz und Kontravarianz (C # und Visual Basic). http://msdn.microsoft.com/en-us/library/ee207183.aspx