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 Tparameter. Akan menyenangkan untuk dapat mengonversi dengan mulus menggunakan an Action<object>sebagai Action<string>- metode apa pun yang menggunakan objectparameter akan baik-baik saja ketika disajikan dengan a stringsebagai 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!