Varyans, yalnızca güvenli bir şekilde desteklenecek - aslında, CLR'nin zaten sahip olduğu yetenekler kullanılarak. Bu nedenle, a'yı List<Banana>
bir List<Fruit>
(veya her neyse) olarak kullanmaya çalışma kitabında verdiğim örnekler hala işe yaramayacak - ancak diğer birkaç senaryo işe yarayacak.
İlk olarak, yalnızca arayüzler ve temsilciler için desteklenecektir.
İkinci olarak, arayüz / temsilcinin yazarının tip parametrelerini in
(kontravans için) veya out
(kovaryans için ) olarak dekore etmesini gerektirir . En bariz örnek, IEnumerable<T>
yalnızca ondan değer "çıkarmanıza" izin verendir - yenilerini eklemenize izin vermez. Bu olacak IEnumerable<out T>
. Bu, tür güvenliğine hiç zarar vermez, ancak örneğin IEnumerable<string>
return IEnumerable<object>
için bildirilen bir yöntemden bir döndürmenize izin verir .
Contravariance, arayüzleri kullanmak için somut örnekler vermek daha zordur, ancak bir delege ile kolaydır. Düşünün Action<T>
- bu sadece bir T
parametre alan bir yöntemi temsil eder . Sorunsuz dönüştürmek bir kullanabilmek için güzel olurdu Action<object>
bir şekilde Action<string>
bir alan herhangi bir yöntemle - object
parametre bir ile sunulan ne zaman cezası olacak string
yerine. Elbette, C # 2 zaten bir dereceye kadar delegelerin kovaryansına ve kontravansına sahiptir, ancak bir delege türünden diğerine gerçek bir dönüşüm yoluyla (yeni bir örnek oluşturma) - örnekler için bkz. P141-144. C # 4 bunu daha genel hale getirecek ve (inanıyorum) dönüşüm için yeni bir örnek oluşturmaktan kaçınacaktır. (Bunun yerine bir referans dönüştürme olacaktır.)
Umarım bu biraz açıklığa kavuşur - mantıklı değilse lütfen bana bildirin!