2010-01-20 15 views
12

यह कोड "आउट मान" आउटपुट करता है।एक अपवाद फेंकने वाली विधि से आउट/रेफ पैरामीटर के माध्यम से मूल्य कैसे प्राप्त करें?

class P 
{ 
    public static void Main() 
    { 
    string arg = null; 
    try 
    { 
     Method(out arg); 
    } 
    catch 
    { 
    } 
    Console.WriteLine(arg); 
    } 
    public static void Method(out string arg) 
    { 
    arg = "out value"; 
    throw new Exception(); 
    } 
} 

लेकिन यह कोई नहीं करता है।

class P 
{ 
    public static void Main() 
    { 
    object[] args = new object[1]; 
    MethodInfo mi = typeof(P).GetMethod("Method"); 
    try 
    { 
     mi.Invoke(null, args); 
    } 
    catch 
    { 
    } 
    Console.WriteLine(args[0]); 
    } 
    public static void Method(out string arg) 
    { 
    arg = "out value"; 
    throw new Exception(); 
    } 
} 

मैं दोनों "बाहर मूल्य" और एक अपवाद जब प्रतिबिंब का उपयोग कर कैसे मिल सकता है?

+3

अच्छा सवाल। लेकिन यदि कोई विधि फेंकता है तो आपको 'आउट' मान पर भरोसा नहीं करना चाहिए। –

+1

+1, बहुत अच्छा सवाल, निश्चित रूप से मुझे इसे आजमा देना था :) मैं अनुमान लगाता हूं कि आपका मूल चर आवंटित फ़ंक्शन में पास नहीं होता है, यह एक प्रति प्राप्त करता है, और वह प्रतिलिपि सफल होने पर मूल में वापस दिखाई देती है पूरा होने (जो निश्चित रूप से नहीं होता है)। – slugster

+0

@slugster: आपकी अटकलें सही है। मुझे संदेह है कि प्रतिबिंब के साथ ऐसा करने का कोई तरीका नहीं है। –

उत्तर

-1

यदि विधि अपवाद फेंकता है तो बाहर पैरामीटर अपरिभाषित है। आप इसे पहले उदाहरण में शून्य करने के लिए प्रारंभ नहीं कर सकते हैं, तो कोड संकलित नहीं होगा।

तो, यह अपवर्तक विधि के लिए समझ में आता है कि विधि अपवाद को फेंकने पर अपरिभाषित मान वापस न करे।

+0

"विधि पैरामीटर अपरिभाषित है यदि विधि अपवाद फेंकता है।" क्या आप इस के लिए spec उद्धृत कर सकते हैं? "आप इसे पहले उदाहरण में शून्य करने के लिए प्रारंभ नहीं कर सकते हैं, तो कोड संकलित नहीं होगा।" यह परिणाम की "अनिश्चितता" का सबूत नहीं है। यह केवल साबित करता है कि यह सी # कंपाइलर नियमों के अनुसार "निश्चित रूप से असाइन नहीं किया गया" है। "निश्चित रूप से असाइन नहीं किया गया" का मतलब अनिर्धारित या असाइन नहीं किया गया है। यह एक मौलिक रूप से अलग बात है। –

+2

>> "विधि पैरामीटर अपरिभाषित है यदि विधि अपवाद फेंकता है।" ऐसा क्यों है? हां, यदि आप प्रारंभिकरण को हटाते हैं तो कोड संकलित नहीं होगा। लेकिन विधि() में फेंकने की उपस्थिति के कारण नहीं, बल्कि मुख्य में खाली पकड़ ब्लॉक की वजह से, यानी सभी निष्पादन पथ वास्तविक उपयोग से पहले तर्क के मूल्य को प्रारंभ नहीं करते हैं। –

+0

-1, आउट var अपरिभाषित नहीं है - कोड चलाएं और आप देखेंगे। – slugster

1

अपवाद ने MethodInfo.Invoke() में कोड को छोड़ दिया है जो स्टैक फ्रेम से [आउट] मान को ऑब्जेक्ट सरणी में वापस कॉपी करता है। स्टैक फ्रेम पर मूल्य जो Invoke() बनाया गया है वैसे ही व्यवहार करता है जैसे यह आपके पहले स्निपेट में करता है। लेकिन वही है जहां समानताएं समाप्त होती हैं।

1

एकमात्र तरीका आपकी विधि को इस तरह से अधिभारित करना है कि अपवाद की संभावना के लिए खाते हैं और फिर "बस मामले में" पास करते हैं। निम्नलिखित मुझे लगता है कि आप क्या सोच रहे हैं। समस्या यह है कि मैं समझता हूं कि प्रतिबिंब संदर्भ द्वारा पारित पते के प्रत्यक्ष हेरफेर नहीं करता है। पते तब तक प्रभावित नहीं होते जब तक कि विधि अंत बिंदु अपवाद के बिना पहुंचा न जाए। शायद एमएस से स्मृति स्मृति या स्मृति सुरक्षा योजना।

class P 
    { 
     public static void Main() 
     { 
      object[] args = { "1", new Exception()}; 
      MethodInfo mi = typeof(P).GetMethod("Method"); 
      try 
      { 
       mi.Invoke(null, args); 
      } 
      catch 
      { 
      } 
      Console.WriteLine(args[0].ToString()); 
      Console.WriteLine(args[1].ToString()); 
     } 
     public static void Method(ref string arg, ref Exception ex) 
     { 
      try 
      { 
       arg = "out value"; 
       throw new Exception(); 
      } 
      catch (Exception exc) 
      { 
       ex = exc; 
      } 
     } 
} 
+0

मुझे नहीं लगता कि यह मौलिक समस्या हल करता है। अगर हमारे पास बुलाए गए तरीके के लिए उस तरह का नियंत्रण था, तो हम प्रतिबिंब का उपयोग नहीं करेंगे। मुद्दा यह है कि, इस तरह की विधि कहीं और मौजूद हो सकती है और हमें प्रतिबिंब का उपयोग करके इसे कॉल करने की आवश्यकता हो सकती है। हम यह कैसे करेंगे? मुझे नहीं लगता कि यह संभव है। –

+0

मैं मानता हूं कि वर्णित तरीके से यह संभव नहीं है। मुझे इस पद से समझ मिली कि उसके पास परिलक्षित विधि का नियंत्रण था, इसलिए मैंने सोचा कि मैं एक काम-आसपास का प्रस्ताव दूंगा। –

0

मैं पैरामीटर के बजाय परिणाम ऑब्जेक्ट को वापस करने के लिए विधि को बदलने का प्रस्ताव दूंगा। परिणाम वस्तु में अपवाद और आपके तर्क का मूल्य भी हो सकता है।

+0

जैसा कि मैंने @ जोएल के जवाब में टिप्पणी में उल्लेख किया है, सवाल एक मौलिक है। क्या होगा यदि हमारे पास लक्ष्य विधि पर कोई नियंत्रण नहीं था। एक मनमानी विधि है और हमें प्रतिबिंब का उपयोग करके इसे कॉल करने की आवश्यकता है। हम यह कैसे करेंगे? –

0

यदि समस्या है, तो आप कैसे अपवाद करते हैं कि आप एक अपवाद हुआ है और आप Windows फॉर्म एप्लिकेशन के साथ काम कर रहे हैं, क्या आपने थ्रेड अपवाद ईवेंट को देखने और SetUnhandledExceptionMode() के साथ संयोजन करने का प्रयास किया है?

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)   
{    
    HandleException(e.Exception);   
} 
+0

आउटपुट पैरामीटर का मूल्य कहां है? मुझे लगता है कि आपने सवाल को गलत समझा। यह अपवाद को पकड़ने के बारे में नहीं है। समस्या यह है कि प्रतिबिंब का उपयोग करते समय, यदि कैली फेंकता है, तो आउटपुट पैरामीटर का मान असाइन नहीं किया जाता है। यह समस्या का समाधान नहीं करता है। –