Apa perbedaan antara <out T>
dan <T>
? Sebagai contoh:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
Apa perbedaan antara <out T>
dan <T>
? Sebagai contoh:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
Jawaban:
Kata out
kunci dalam generik digunakan untuk menunjukkan bahwa tipe T di antarmuka adalah kovarian. Lihat Covariance dan contravariance untuk detailnya.
Contoh klasiknya adalah IEnumerable<out T>
. Karena IEnumerable<out T>
kovarian, Anda diperbolehkan melakukan hal berikut:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
Baris kedua di atas akan gagal jika ini bukan kovarian, meskipun secara logis seharusnya bekerja, karena string berasal dari objek. Sebelum variasi dalam antarmuka umum ditambahkan ke C # dan VB.NET (dalam .NET 4 dengan VS 2010), ini adalah kesalahan waktu kompilasi.
Setelah .NET 4, IEnumerable<T>
ditandai kovarian, dan menjadi IEnumerable<out T>
. Karena IEnumerable<out T>
hanya menggunakan elemen di dalamnya, dan tidak pernah menambahkan / mengubahnya, aman untuk memperlakukan kumpulan string yang dapat dihitung sebagai kumpulan objek yang dapat dihitung, yang berarti kovarian .
Ini tidak akan bekerja dengan tipe seperti IList<T>
, karena IList<T>
memiliki Add
metode. Misalkan ini diizinkan:
IList<string> strings = new List<string>();
IList<object> objects = strings; // NOTE: Fails at compile time
Anda kemudian dapat menelepon:
objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
Ini tentu saja akan gagal - jadi IList<T>
tidak dapat ditandai kovarian.
Ada juga, btw, opsi untuk in
- yang digunakan oleh hal-hal seperti antarmuka perbandingan. IComparer<in T>
, misalnya, bekerja dengan cara yang berlawanan. Anda dapat menggunakan beton IComparer<Foo>
secara langsung sebagai IComparer<Bar>
if Bar
adalah subclass Foo
, karena IComparer<in T>
antarmuka bersifat contravariant .
Image
adalah kelas abstrak;) Anda dapat melakukannya new List<object>() { Image.FromFile("test.jpg") };
tanpa masalah, atau Anda dapat melakukannya new List<object>() { new Bitmap("test.jpg") };
juga. Masalah dengan Anda adalah yang new Image()
tidak diizinkan (Anda tidak dapat melakukan var img = new Image();
keduanya)
IList<object>
adalah contoh aneh, jika Anda mau object
, Anda tidak perlu obat generik.
Untuk mengingat dengan mudah penggunaan in
dan out
kata kunci (juga kovarian dan contravariance), kita dapat gambar pewarisan sebagai pembungkus:
String : Object
Bar : Foo
mempertimbangkan,
class Fruit {}
class Banana : Fruit {}
interface ICovariantSkinned<out T> {}
interface ISkinned<T> {}
dan fungsinya,
void Peel(ISkinned<Fruit> skinned) { }
void Peel(ICovariantSkinned<Fruit> skinned) { }
Fungsi yang menerima ICovariantSkinned<Fruit>
akan dapat menerima ICovariantSkinned<Fruit>
atau ICovariantSkinned<Bananna>
karena ICovariantSkinned<T>
merupakan antarmuka kovarian dan Banana
merupakan jenis Fruit
,
fungsi yang menerima ISkinned<Fruit>
hanya akan dapat menerima ISkinned<Fruit>
.
" out T
" berarti tipe T
itu "kovarian". Itu membatasi T
muncul hanya sebagai nilai yang dikembalikan (keluar) dalam metode kelas generik, antarmuka atau metode. Implikasinya adalah Anda dapat menggunakan tipe / antarmuka / metode yang setara dengan tipe super T
.
Misalnya ICovariant<out Dog>
dapat dilemparkan ke ICovariant<Animal>
.
out
penegakan yang T
dapat dikembalikan hanya, sampai saya membaca jawaban ini. Seluruh konsep lebih masuk akal sekarang!
Dari tautan yang Anda poskan ....
Untuk parameter tipe umum, kata kunci keluar menentukan bahwa parameter tipe adalah kovarian .
EDIT : Sekali lagi, dari tautan yang Anda poskan
Untuk informasi lebih lanjut, lihat Covariance dan Contravariance (C # dan Visual Basic). http://msdn.microsoft.com/en-us/library/ee207183.aspx