2016-02-10 21 views
6

Neden bir temsilci örneğini örneğini T genel türüne çeviremiyoruz? Genel bir tür için temsilci açılamıyor T

yani MulticastDelegate türetilen bir tür bir temsilci olduğu T, bir örneğini oluşturan bir yardımcı yöntem CreateDelegate düşünün.

T CreateDelegate<T>() {… } 

Ne yazık ki jenerik aşağıdaki derleme hatayı veren MulticastDelegate türetilen bir türüne T sınırlamak için izin vermez:

Constraint cannot be special class 'System.MulticastDelegate'

Bununla birlikte, bu yarar yöntem T olmadığını kontrol edilir MulticastDelegate ile uyumlu olan ve Yansıma aracılığıyla Delegate::CreateDelegate aracılığıyla bir temsilci oluşturma. Ben object ilk döküm ve sonra T için iyi çalışır eğer Ancak

Cannot convert type 'System.Delegate' to 'T'

:

biz T için Delegate::CreateDelegate sonucunu döküm çalışırsanız Ama, biz şu derleme hatası alırsınız
T h = (T) ((object) Delegate.CreateDelegate(typeof(T), target, m)); 

Niçin doğrudan temsilci T'ye yapamıyoruz?

+0

bunu yapar: '' T h = Delegate.CreateDelegate (typeof (T), hedef, m) T; ''? –

+0

Evet, işe yarıyor. Ve daha da az mantıklı. IMHO, her iki operatörün ('' 've _cast_) davranışları tutarlı olmalıdır. –

+0

bu yol, daha sonra döküm nesnesinden T'den daha güvenlidir, eğer döküm başarısız olursa size boş verir –

cevap

10

C# dili tipi X'ten bir döküm Y yazın edip statik çek getirir geçerlidir - bu derleyici garanti uyumluluğu (belirli bir dereceye kadar) ve derleme üzerinde kadar net hataları reddedebilir ki anlamda yapar mı yani -zaman. Kısıtsız bir jenerik tip T ve System.Delegate doğrudan ortak hiçbir şey yoktur. Ancak, object'a gönderildiğinde, derleyici, her türününnumaralı türünde olduğunu bildiğinden, yayınlamaya izin verir. Bu, belirli bir durumda bir çalışma zamanı türü denetimi başarısız olmayacağı anlamına gelmez.

as işleci, geçersiz bir yayın için bir istisna oluşturmayacağı için biraz daha izin vericidir. Derleyici ayrıca statik kontrollerin uygulanmasında daha az sıkıdır. Özel durumunuzda, ara dökümünü object'a aktarabilir ve as T'u kullanabilirsiniz. Ancak, bu gerekli olan bir tane, as yalnızca sınıf türlerinde çalışır, bu nedenle where T : class kısıtlamasını uygulamanız gerekir.

Öyleyse yöntemi aşağıdaki gibi görünür (basitleştirilmiş) olacaktır:

public T CreateDelegate<T>(…) where T : class 
{ 
    return Delegate.CreateDelegate(typeof(T), …) as T; 
} 

@usr öne sürdüğü gibi, önerilen bir okuma Eric Lippert blogu, örneğin bir this article on casts and type parameters.

İlgili konular