2009-03-28 17 views
25

मैं CLR स्क्रिप्टिंग के लिए .NET On-the-Fly संकलक लिख रहा हूँ और चाहता हूँ निष्पादन विधि सामान्य स्वीकार्य बनाने:ऑपरेटर और सामान्य वर्गों

object Execute() 
{ 
    return type.InvokeMember(..); 
} 

T Execute<T>() 
{ 
    return Execute() as T; /* doesn't work: 
    The type parameter 'T' cannot be used with the 'as' operator because 
    it does not have a class type constraint nor a 'class' constraint */ 

    // also neither typeof(T) not T.GetType(), so on are possible 

    return (T) Execute(); // ok 
} 

लेकिन मुझे लगता है ऑपरेटर as बहुत उपयोगी हो जाएगा: यदि परिणाम प्रकार T तरीका नहीं है एक अपवाद के बजाय null वापस आ जाएगा! यह करना संभव है?

उत्तर

49

आप अपने विधि घोषणा करता है, उदा को

where T : class 

जोड़ने की जरूरत

T Execute<T>() where T : class 
{ 

वैसे, एक सुझाव के रूप में, जेनेरिक रैपर वास्तव में बहुत अधिक मूल्य नहीं जोड़ता है। फोन करने वाले लिख सकते हैं:

MyClass c = whatever.Execute() as MyClass; 

या अगर वे पर फेंक करना चाहते हैं असफल:

MyClass c = (MyClass)whatever.Execute(); 

सामान्य आवरण विधि इस प्रकार है:

MyClass c = whatever.Execute<MyClass>(); 

सभी तीन संस्करणों वास्तव में बताने की वही तीन इकाइयां, केवल अलग-अलग ऑर्डर में, इसलिए कोई भी आसान या कोई सुविधाजनक नहीं है, और फिर भी जेनेरिक संस्करण क्या हो रहा है छुपाता है, जबकि "कच्चे" संस्करण प्रत्येक यह स्पष्ट करते हैं कि वहां डब्ल्यू बीमार एक फेंक या null हो।

(यदि आपका उदाहरण आपके वास्तविक कोड से सरलीकृत है तो यह आपके लिए अप्रासंगिक हो सकता है)।

+0

धन्यवाद आपके उत्तर के लिए बहुत कुछ। मैं इसका उपयोग करूंगा, उत्तर के रूप में जांच और चिह्नित करूंगा। और, मेरे पास अगला कोड उपयोग है: MyClass c = compiler.Execute (); मुझे लगता है कि यह MyClass सी = compiler.Execute() MyClass के रूप में बेहतर है; (अंदर जांचें तो बाहर बेहतर है, मुझे लगता है) – abatishchev

+0

लेकिन चेक अभी भी बाहर की जरूरत है - शून्य के लिए जांच! :) उपयोगकर्ता को 'MyClass' के रूप में लिखकर, आप इसे और अधिक स्पष्ट करते हैं कि शून्य की जांच आवश्यक है। –

+0

एचएम .. ऐसा लगता है कि आप सही हैं! मैं 'सामान्य' निष्पादन() का उपयोग करने की अनुशंसा करूंगा, लेकिन अंत उपयोगकर्ता के लिए यह 'असामान्य' निष्पादन(), 'जेनेरिक प्रयोग' के अलावा कुछ भी उपयोगी हो सकता है :) – abatishchev

11

आप as ऑपरेटर का उपयोग किसी सामान्य प्रकार के साथ बिना किसी प्रतिबंध के कर सकते हैं। चूंकि as ऑपरेटर यह प्रतिनिधित्व करने के लिए शून्य का उपयोग करता है कि यह प्रकार का नहीं था, इसलिए आप इसे मूल्य प्रकारों पर उपयोग नहीं कर सकते हैं। यदि आप obj as T का उपयोग करना चाहते हैं, Tमें एक संदर्भ प्रकार होने के लिए है।

T Execute<T>() where T : class 
{ 
    return Execute() as T; 
} 
1

ऐसा लगता है कि तुम सिर्फ प्रकार उपयोगकर्ता चाहता है कास्टिंग के लिए एक आवरण विधि जोड़ रहे हैं, इस प्रकार केवल निष्पादन के लिए भूमि के ऊपर जोड़ने। उपयोगकर्ता,

int result = Execute<int>(); 

लिखने के लिए से

int result = (int)Execute(); 

बहुत अलग नहीं है तुम बाहर संशोधक का उपयोग फोन करने वाले का दायरे में एक चर में परिणाम लिखने के लिए कर सकते हैं और एक बूलियन ध्वज वापसी यह बताने के लिए कि क्या यह सफल हुआ:

bool Execute<T>(out T result) where T : class 
{ 
    result = Execute() as T; 
    return result != null; 
} 
1

क्या कोई मौका है कि निष्पादन() एक मूल्य प्रकार वापस कर सकता है? यदि ऐसा है, तो आपको कक्षा प्रकारों के लिए ईरविकियर की विधि और मूल्य प्रकारों के लिए एक और सामान्य विधि की आवश्यकता है।इस प्रकार दिखाई देंगे:

Nullable<T> ExecuteForValueType<T> where T : struct 

तर्क यह है कि विधि के अंदर

object rawResult = Execute(); 

तो कह सकते हैं कि, आप rawResult के प्रकार के हो जाते हैं और देखें कि क्या वह टी को सौंपा जा सकता होगा:

Nullable<T> finalReturnValue = null; 

Type theType = rawResult.GetType(); 
Type tType = typeof(T); 

if(tType.IsAssignableFrom(theType)) 
{ 
    finalReturnValue = tType;  
} 

return finalReturnValue; 

अंत में, अपने मूल निष्पादन संदेश को समझें कि कौन सा टी है (वर्ग या संरचना प्रकार), और उपयुक्त कार्यान्वयन को कॉल करें।

नोट: यह किसी न किसी स्मृति से है। मैंने यह एक साल पहले किया था और शायद हर विवरण याद नहीं है। फिर भी, मुझे आशा है कि आपको सामान्य दिशा में इंगित करने में मदद मिलेगी।

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