2016-02-10 18 views
6

पर प्रतिनिधि को नहीं डाला जा सकता है हम प्रतिनिधि का एक सामान्य प्रकार T पर क्यों नहीं डाल सकते?एक सामान्य प्रकार टी

एक उपयोगिता विधि CreateDelegate कि टी है, जो एक प्रतिनिधि है, यानी एक प्रकार MulticastDelegate से प्राप्त होता है का एक उदाहरण बनाता है पर विचार करें।

T CreateDelegate<T>() {… } 

दुर्भाग्य से जेनरिक एक प्रकार MulticastDelegate निम्नलिखित संकलन त्रुटि देने से प्राप्त होने वाले T में रोके करने के लिए अनुमति नहीं देता:

Constraint cannot be special class 'System.MulticastDelegate'

फिर भी, इस उपयोगिता विधि है कि T जाँच कर रहा है MulticastDelegate साथ संगत है और Delegate::CreateDelegate के माध्यम से प्रतिबिंब के माध्यम से एक प्रतिनिधि बनाते हैं। लेकिन, अगर हम T को Delegate::CreateDelegate का परिणाम कास्ट करने के लिए प्रयास करते हैं, हम निम्नलिखित संकलन त्रुटि मिल जाएगा:

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

हालांकि, अगर मैं यह पहली बार object लिए डाली और फिर T लिए यह ठीक से काम करेगा:

T h = (T) ((object) Delegate.CreateDelegate(typeof(T), target, m)); 

हम सीधे टी को प्रतिनिधि क्यों नहीं दे सकते?

+0

यह काम करता है: 'टी एच = प्रतिनिधि। क्रेतेडिलेट (टाइपोफ (टी), लक्ष्य, एम) टी के रूप में;' '? –

+0

हाँ, यह काम करता है। और, यह भी कम समझ में आता है। आईएमएचओ दोनों ऑपरेटरों का व्यवहार ('as' और _cast_) संगत होना चाहिए। –

+0

इस तरह ऑब्जेक्ट से टी तक ऑब्जेक्ट कास्टिंग करने से अधिक सुरक्षित है, अगर यह –

उत्तर

10

सी # भाषा एक स्थिर जांच प्रकार एक्स से एक डाली Y टाइप करने के लिए है कि क्या लगाता मान्य है - यानी कि क्या यह है कि में भावना बनाता संकलक कर सकते हैं (कुछ हद तक) गारंटी अनुकूलता और त्रुटियों है कि के रूप में संकलन पर स्पष्ट अस्वीकार -पहर। एक अनियंत्रित जेनेरिक प्रकार T और System.Delegate में कुछ भी सामान्य नहीं है। हालांकि, जब object पर डाला गया तो संकलक जानता है कि प्रत्येक प्रकार अनिवार्य रूप से object है, इसलिए यह कास्ट की अनुमति देता है। इसका मतलब यह नहीं है कि किसी विशेष मामले में रन-टाइम प्रकार की जांच विफल नहीं होगी।

as ऑपरेटर थोड़ा और अधिक अनुमोदित है, क्योंकि इससे अन्यथा अमान्य कलाकारों के लिए अपवाद नहीं होगा। स्थिर जांच लागू करने में संकलक भी कम सख्त है। आपके विशेष मामले में यह सहायक है क्योंकि आप इंटरमीडिएट कास्ट object पर छोड़ सकते हैं और as T का उपयोग कर सकते हैं। हालांकि, यह आवश्यक है कि as केवल कक्षा प्रकारों पर काम करता है, इसलिए आपको where T : class बाधा लागू करना होगा।

तो विधि तो इस प्रकार दिखाई देगा (सरलीकृत):

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

रूप @usr का सुझाव दिया, एक की सिफारिश की पढ़ने एरिक Lippert के ब्लॉग, उदा है this article on casts and type parameters

संबंधित मुद्दे