Varians hanya akan didukung dengan cara yang aman - pada kenyataannya, menggunakan kemampuan yang sudah dimiliki CLR. Jadi contoh yang saya berikan dalam buku tentang mencoba menggunakan a List<Banana>
sebagai List<Fruit>
(atau apa pun itu) tetap tidak akan berhasil - tetapi beberapa skenario lain akan berhasil.
Pertama, ini hanya akan didukung untuk antarmuka dan delegasi.
Kedua, memerlukan pembuat antarmuka / delegasi untuk menghias parameter tipe sebagai in
(untuk kontradiksi) atau out
(untuk kovarian). Contoh yang paling jelas adalah IEnumerable<T>
yang hanya memungkinkan Anda mengambil nilai "keluar" darinya - tidak memungkinkan Anda menambahkan nilai baru. Itu akan menjadi IEnumerable<out T>
. Itu tidak mengganggu keamanan tipe sama sekali, tetapi memungkinkan Anda mengembalikan IEnumerable<string>
dari metode yang dideklarasikan untuk dikembalikan IEnumerable<object>
misalnya.
Kontradiksi lebih sulit untuk memberikan contoh konkret untuk menggunakan antarmuka, tetapi mudah dengan delegasi. Pertimbangkan Action<T>
- itu hanya mewakili metode yang mengambil T
parameter. Akan menyenangkan untuk dapat mengonversi dengan mulus menggunakan an Action<object>
sebagai Action<string>
- metode apa pun yang menggunakan object
parameter akan baik-baik saja ketika disajikan dengan a string
sebagai gantinya. Tentu saja, C # 2 sudah memiliki kovariansi dan kontradiksi delegasi sampai batas tertentu, tetapi melalui konversi aktual dari satu jenis delegasi ke jenis lainnya (membuat instans baru) - lihat P141-144 sebagai contoh. C # 4 akan membuat ini lebih umum, dan (saya percaya) akan menghindari membuat contoh baru untuk konversi. (Alih-alih, ini akan menjadi konversi referensi.)
Semoga ini sedikit menyelesaikannya - beri tahu saya jika tidak masuk akal!