c# - क्यों सी#में एक अपवाद पकड़ और rethrow?
exception-handling try-catch (10)
मैं अनुच्छेद सी # - धारावाहिक डीटीओ पर डेटा ट्रांसफर ऑब्जेक्ट देख रहा हूं।
लेख में कोड का यह टुकड़ा शामिल है:
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
throw ex;
}
}
शेष लेख सचेत और उचित (नोब के लिए) दिखता है, लेकिन यह कोशिश-पकड़-फेंक एक WtfException फेंकता है ... क्या यह बिल्कुल अपवादों को संभालने के बराबर नहीं है?
Ergo:
public static string SerializeDTO(DTO dto) {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
या क्या मैं सी # में त्रुटि प्रबंधन के बारे में कुछ मौलिक याद कर रहा हूं? यह जावा (शून्य चेक अपवाद) के समान ही है, है ना? ... यही है, वे दोनों परिष्कृत सी ++।
स्टैक ओवरफ़्लो प्रश्न फिर से फेंकने वाले पैरामीटर-कम पकड़ के बीच अंतर और कुछ भी नहीं कर रहा है? ऐसा लगता है कि मेरी विवाद का समर्थन करना है कि कोशिश-पकड़-फेंक-नो-ऑप है।
संपादित करें:
भविष्य में इस धागे को ढूंढने वाले किसी भी व्यक्ति के लिए संक्षेप में ...
ऐसा न करें
try {
// Do stuff that might throw an exception
}
catch (Exception e) {
throw e; // This destroys the strack trace information!
}
समस्या के मूल कारण की पहचान करने के लिए स्टैक ट्रेस जानकारी महत्वपूर्ण हो सकती है!
कर
try {
// Do stuff that might throw an exception
}
catch (SqlException e) {
// Log it
if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
// Do special cleanup, like maybe closing the "dirty" database connection.
throw; // This preserves the stack trace
}
}
catch (IOException e) {
// Log it
throw;
}
catch (Exception e) {
// Log it
throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
// Normal clean goes here (like closing open files).
}
कम विशिष्ट लोगों (जैसे जावा की तरह) से पहले अधिक विशिष्ट अपवादों को पकड़ें।
संदर्भ:
क्या यह बिल्कुल अपवादों को संभालने के बराबर नहीं है?
बिल्कुल नहीं, यह वही नहीं है। यह अपवाद के stacktrace रीसेट करता है। हालांकि मैं मानता हूं कि यह शायद एक गलती है, और इस प्रकार खराब कोड का एक उदाहरण है।
अधिकांश जवाब परिदृश्य कैच-लॉग-रीथ्रो के बारे में बात करते हैं।
अपने कोड में इसे लिखने के बजाय एओपी का उपयोग करने पर विचार करें, विशेष रूप से Postsharp.Diagnostic.Toolkit सहित पैरामीटर वैल्यू और IncludeThisArgument
आप पूर्व को फेंकना नहीं चाहते हैं - क्योंकि यह कॉल स्टैक खो देगा। अपवाद हैंडलिंग (एमएसडीएन) देखें।
और हाँ, कोशिश करें ... पकड़ कुछ भी उपयोगी नहीं कर रहा है (कॉल स्टैक खोने के अलावा - तो यह वास्तव में बदतर है - जब तक कि किसी कारण से आप इस जानकारी का पर्दाफाश नहीं करना चाहते थे)।
आपके द्वारा पोस्ट किए गए कोड में उदाहरण में, वास्तव में, अपवाद को पकड़ने में कोई बात नहीं है क्योंकि पकड़ पर कुछ भी नहीं किया गया है, यह सिर्फ फिर से उड़ाया गया है, वास्तव में यह कॉल से अधिक नुकसान होता है क्योंकि कॉल स्टैक खो जाता है ।
हालांकि, अपवाद की स्थिति में कुछ तर्क करने के लिए अपवाद प्राप्त होगा (उदाहरण के लिए फ़ाइल लॉक के एसक्यूएल कनेक्शन को बंद करना, या केवल कुछ लॉगिंग), इसे वापस कॉल करने के लिए कॉलिंग कोड पर फेंक दें। यह फ्रंट एंड कोड की तुलना में एक व्यापार परत में अधिक आम होगा क्योंकि आप अपवाद को संभालने के लिए अपनी व्यावसायिक परत को लागू करने वाले कोडर को चाहते हैं।
फिर से पुन: पुन: प्रयास करने के लिए, आपके द्वारा पोस्ट किए गए उदाहरण में अपवाद को पकड़ने में कोई बिंदु नहीं है। ऐसा मत करो!
ऐसा मत करो,
try
{
...
}
catch(Exception ex)
{
throw ex;
}
आप स्टैक ट्रेस जानकारी खो देंगे ...
या तो करो,
try { ... }
catch { throw; }
या
try { ... }
catch (Exception ex)
{
throw new Exception("My Custom Error Message", ex);
}
यदि आप अलग-अलग अपवादों को संभालने वाले हैं, उदाहरण के लिए, यदि आप पुनर्विचार करना चाहते हैं तो एक कारण यह है कि
try
{
...
}
catch(SQLException sex)
{
//Do Custom Logging
//Don't throw exception - swallow it here
}
catch(OtherException oex)
{
//Do something else
throw new WrappedException("Other Exception occured");
}
catch
{
System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
throw; //Chuck everything else back up the stack
}
कोड रखने के लिए मेरा मुख्य कारण:
try
{
//Some code
}
catch (Exception e)
{
throw;
}
इसलिए मैं पकड़ में ब्रेकपॉइंट कर सकता हूं, जिसमें तत्काल अपवाद वस्तु है। मैं विकास / डिबगिंग करते समय यह बहुत कुछ करता हूं। बेशक, संकलक मुझे सभी अप्रयुक्त ई के बारे में चेतावनी देता है, और आदर्श रूप से उन्हें रिलीज निर्माण से पहले हटा दिया जाना चाहिए।
हालांकि वे डीबगिंग के दौरान अच्छे हैं।
जबकि कई अन्य उत्तरों अच्छे उदाहरण प्रदान करते हैं कि आप एक अपवाद को फिर से क्यों पकड़ना चाहते हैं, किसी ने भी 'आखिरकार' परिदृश्य का उल्लेख नहीं किया है।
इसका एक उदाहरण यह है कि आपके पास एक तरीका है जिसमें आप कर्सर सेट करते हैं (उदाहरण के लिए प्रतीक्षा कर्सर के लिए), विधि में कई निकास बिंदु हैं (उदाहरण के लिए अगर () वापसी;) और आप यह सुनिश्चित करना चाहते हैं कि कर्सर रीसेट हो विधि का अंत
ऐसा करने के लिए आप सभी कोड को कोशिश / पकड़ / अंत में लपेट सकते हैं। आखिर में कर्सर को सही कर्सर पर सेट करें। ताकि आप किसी भी वैध अपवाद को दफन न करें, इसे पकड़ में दोबारा डालें।
try
{
Cursor.Current = Cursors.WaitCursor;
// Test something
if (testResult) return;
// Do something else
}
catch
{
throw;
}
finally
{
Cursor.Current = Cursors.Default;
}
प्रथम; जिस तरह से लेख में कोड यह बुरा है। throw ex
उस बिंदु के अपवाद में कॉल स्टैक को रीसेट कर देगा जहां यह फेंक स्टेटमेंट है; वास्तव में अपवाद कहां बनाया गया था, इस बारे में जानकारी खोना।
दूसरा, यदि आप बस उस तरह पकड़ते हैं और फिर से फेंकते हैं, तो मुझे कोई अतिरिक्त मूल्य दिखाई नहीं देता है, उपरोक्त कोड उदाहरण उतना ही अच्छा होगा (या, throw ex
दिया गया है, यहां तक कि बेहतर भी) बिना प्रयास किए।
हालांकि, ऐसे मामले हैं जहां आप अपवाद को पकड़ना और पुनर्स्थापित करना चाहते हैं। लॉगिंग उनमें से एक हो सकता है:
try
{
// code that may throw exceptions
}
catch(Exception ex)
{
// add error logging here
throw;
}
यह निर्भर करता है कि आप कैच ब्लॉक में क्या कर रहे हैं, और यदि आप कॉलिंग कोड पर त्रुटि पास करना चाहते हैं या नहीं।
आप कह सकते हैं Catch io.FileNotFoundExeption ex
और फिर वैकल्पिक फ़ाइल पथ या कुछ ऐसे का उपयोग करें, लेकिन फिर भी त्रुटि को फेंक दें।
Throw Ex
बजाए Throw Ex
आप पूरे स्टैक ट्रेस को रखने की अनुमति देते हैं। थ्रो स्टेटमेंट से स्टैक ट्रेस को पूर्ववत करें (मुझे आशा है कि यह समझ में आता है)।