C # में एक अपवाद को क्यों पकड़ना और पुनर्जीवित करना?


557

मैं सीरीयल डीटीओ पर डेटा ट्रांसफर ऑब्जेक्ट सी # - आर्टिकल देख रहा हूं ।

लेख में कोड का यह टुकड़ा शामिल है:

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;
    }
}

लेख का बाकी हिस्सा समझदार और उचित है (एक noob के लिए), लेकिन वह कोशिश-कैच-थ्रो 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();
}

या क्या मुझे C # में त्रुटि से निपटने के बारे में कुछ मौलिक याद आ रही है? यह जावा (माइनस चेक अपवाद) के रूप में बहुत अधिक है, है ना? ... अर्थात्, वे दोनों C ++ को परिष्कृत करते हैं।

स्टैक ओवरफ्लो प्रश्न पैरामीटर को फिर से फेंकने और कम पकड़ने के बीच का अंतर? मेरे विवाद का समर्थन करने के लिए लगता है कि कोशिश-पकड़-फेंक एक नो-ऑप है।


संपादित करें:

भविष्य में इस धागे को खोजने वाले किसी भी व्यक्ति के लिए बस संक्षेप में ...

ऐसा न करें

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).
}

कम विशिष्ट लोगों (जावा की तरह) से पहले अधिक विशिष्ट अपवादों को पकड़ो।


संदर्भ:


8
अच्छा सारांश; अंत में ब्लॉक सहित के लिए अतिरिक्त अंक।
फ्रेड्रिक मॉक

मैं जोड़ना चाहूंगा कि आप "फेंक" का उपयोग कर सकते हैं ई। डीटा संग्रह में "फेंक" से पहले विधि में भेजे गए मापदंडों को जोड़कर और भी अधिक सहायक होने के लिए; कथन
माइकल बहिग

@MickTheWarMachineDesigner (और अंशकालिक चित्रकार)। है ना? आप माइक्रोसाइट Suckwell (संभवतः सब कुछ मुझे पता है के लिए 2005 के बाद से) अपवादों को संभालने की बात कर रहे हैं। मैं सामान्य रूप से अपवाद हैंडलिंग के बारे में बात कर रहा था। और हाँ मैंने कुछ सीखा है जब से मैंने यह पूरी तरह से एजीआरओ पोस्ट किया है .... लेकिन हाँ, मैं स्वीकार करता हूं कि आपके पास वैध बिंदु है, लेकिन मुझे लगता है कि आपने वास्तविक बिंदु को याद किया है; यदि मेरा आशय आपकी समझ में आ रहा हो? यह प्रश्न C # में सामान्य अपवाद हैंडलिंग के बारे में है; और अधिक विशेष रूप से अपवाद के बारे में ... सभी प्रकार के। ठंडा?
corlettk

कृपया अपने प्रश्न में संपादित सारांश अनुभाग को अपने स्वयं के उत्तर में ले जाने पर विचार करें। क्यों, प्रश्न से स्व-उत्तर का संपादन देखें और प्रश्न में उत्तर दिया गया उत्तर दें
डेविड आरआर

2
क्या किसी ने "अंश नहीं हुआ" भाग पर ध्यान नहीं दिया? ऐसा लगता है कि कोड एक पूप के लिए चला गया!
जेसन लोकी स्मिथ

जवाबों:


430

प्रथम; जिस तरह से लेख में कोड यह बुराई है। throw exउस बिंदु के अपवाद को कॉल स्टैक को रीसेट करेगा जहां यह फेंक स्टेटमेंट है; जहां अपवाद वास्तव में बनाया गया था, उसके बारे में जानकारी खोना।

दूसरा, यदि आप उस तरह से पकड़ते हैं और फिर से फेंकते हैं, तो मुझे कोई अतिरिक्त मूल्य नहीं दिखता है, ऊपर दिया गया कोड उदाहरण ट्राइ throw ex-कैच के बिना बस उतना ही अच्छा होगा (या, बिट, और भी बेहतर)।

हालांकि, ऐसे मामले हैं जहां आप अपवाद को पकड़ना और फिर से निकालना चाहते हैं। लॉगिंग उनमें से एक हो सकता है:

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}

6
@Fredrick, सिर्फ फी (हालांकि आप शायद जानते हैं) यदि आप उस exवस्तु का उपयोग नहीं करने जा रहे हैं , तो इसे तुरंत करने की कोई आवश्यकता नहीं है।
इयोन कैंपबेल

78
@ इयॉन: अगर इसकी त्वरित नहीं तो इसे लॉग इन करना मुश्किल होगा।
सैम एक्स

30
हां, मुझे लगता है कि "बुराई" सही के बारे में है ... कोड के एक बड़े निकाय से कहीं फेंक दिए गए शून्य सूचक अपवाद के मामले पर विचार करें। संदेश वेनिला है, स्टैक ट्रेस के बिना आपको "कुछ कहीं अशक्त था" के साथ छोड़ दिया जाता है। अच्छा नहीं है जब उत्पादन मर चुका है; और आपके पास फ्लमिन की समस्या को हल करने के लिए कोई मिनट या उससे कम नहीं है, और इसे खारिज या सुधारें ... अच्छा अपवाद हैंडलिंग यह सोने में वजन के लायक है।
प्रातः

4
क्या यह जावा के लिए भी सही है ... "थ्रो" बनाम "थ्रो एक्स"?
जेसनस्टॉलटज़

8
@ जेसन, इस सवाल को देखें । जावा में, throw exस्टैक्ट्रेस को फिर से शुरू नहीं करता है।
मैथ्यू फ्लेशेन

117

यह मत करो,

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
}

7
क्यों न केवल कैच {थ्रो} को पूरी तरह से छोड़ दिया जाए?
एंथनीवजोन

3
कैच छोड़ने में अभी भी मूल्य है {थ्रो; } विशिष्ट अपवाद प्रकार की पकड़ की एक सूची के निचले हिस्से में यह साबित होता है कि लेखक ने मामले पर विचार किया है, हालांकि एक टिप्पणी समान रूप से पर्याप्त हो सकती है। जब आप कोड पढ़ते हैं तो अनुमान लगाना अच्छी बात नहीं है।
अन्नकूट

87
किसी कारण से, SQLException का नाम मुझे परेशान करता है।
माइकल मायर्स

13
वह कैच (अपवाद) {थ्रो न्यू एक्ससेप्शन (...)} कुछ ऐसा है जो आपको कभी भी, कभी भी, कभी भी नहीं करना चाहिए , सिर्फ इसलिए कि आप अपवाद सूचना को बाधित कर रहे हैं और अपवाद को कॉल स्टैक अप करना अनावश्यक रूप से कठिन बना रहे हैं। केवल एक बार आपको एक प्रकार के अपवाद को पकड़ना चाहिए और दूसरे को तब फेंकना चाहिए जब आप एक अमूर्त परत को लागू कर रहे हों और आपको एक प्रदाता-विशिष्ट अपवाद प्रकार (जैसे SqlException बनाम XmlException) को एक अधिक सामान्य एक (जैसे DataDadingException) में बदलना होगा।
जम्मीकेश

3
@dark_perfect आपको उस तर्क को जांचना चाहिए, विधि की शुरुआत में और ArgumentNullException को वहां फेंक दें (तेजी से विफल)।
आंद्रेई बोजान्टन

56

C # (C # 6 से पहले) CIL को "फ़िल्टर किए गए अपवाद" का समर्थन नहीं करता है, जो VB करता है, इसलिए C # 1-5 में अपवाद को फिर से फेंकने का एक कारण यह है कि आपके पास पकड़ने के समय पर्याप्त जानकारी नहीं है () यह निर्धारित करने के लिए कि क्या आप वास्तव में अपवाद को पकड़ना चाहते थे।

उदाहरण के लिए, VB में आप कर सकते हैं

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... जो अलग-अलग एररकोड मानों के साथ MyException को हैंडल नहीं करेगा। V6 से पहले C # में, आपको MyException को पकड़ना और फिर से फेंकना होगा यदि ErrorCode 123 नहीं था:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

C # 6.0 के बाद से आप VB की तरह ही फ़िल्टर कर सकते हैं :

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}

2
डेव, लेकिन (कम से कम जावा में) आप एक "सामान्य" MyException को नहीं फेंकेंगे, आप एक विशेष अपवाद प्रकार को परिभाषित करेंगे और इसे फेंक देंगे, इसे पकड़ने वाले ब्लॉक में विभेदित-प्रकार के प्रकार की अनुमति दे सकते हैं ... लेकिन हाँ , अगर आपके अपवाद का वास्तुकार नहीं है (मैं JDBC के SQLException (जावा फिर से) यहां सोच रहा हूं, जो घृणित रूप से सामान्य है, और getErrorCode () विधि ... Hmmm को उजागर करता है ... आपको एक बिंदु मिल गया है, यह सिर्फ इतना ही है) मुझे लगता है कि इसे करने का एक बेहतर तरीका है, जहां संभव हो। चीयर्स मेट। मैं आपके समय, बहुत की सराहना करता हूं। कीथ।
corlettk

1
खैर, सवाल यह है कि "C # में एक्सेप्शन कैच और रीथ्रो क्यों?", और यह एक जवाब है। =] ... और यहां तक ​​कि विशेष अपवादों के साथ, अपवाद फ़िल्टर का अर्थ होता है: उस मामले पर विचार करें जहां आप हैं, मान लें कि, एक SqlTimeoutException और एक SqlConnectionResetException को हैंडल कर रहा है, जो दोनों SqlException हैं। अपवाद फ़िल्टर आपको केवल इन दोनों में से एक होने पर SqlException को पकड़ने की अनुमति देते हैं, इसलिए इन दोनों के लिए समान हैंडलिंग के साथ अपनी कोशिश / पकड़ को अव्यवस्थित करने के बजाय, आप "SqlException पूर्व को पकड़ सकते हैं जब पूर्व SqlTimeout अपवाद या पूर्व SqlConnectionResetException है"। (मैं डेव btw नहीं हूँ)
bzlm

3
फ़िल्टर किए गए अपवाद C # 6 में आ रहे हैं!
सर क्रिस्पलॉट

14

कोड होने का मेरा मुख्य कारण जैसे:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

इसलिए मैं पकड़ में एक ब्रेकप्वाइंट हो सकता है, कि एक त्वरित अपवाद वस्तु है। मैं इसे विकसित / डिबगिंग करते समय बहुत कुछ करता हूं। बेशक, संकलक मुझे सभी अप्रयुक्त ई पर चेतावनी देता है, और आदर्श रूप से उन्हें रिलीज़ बिल्ड से पहले हटा दिया जाना चाहिए।

वे हालांकि डिबगिंग के दौरान अच्छे हैं।


1
हाँ, मैं उस एक का भुगतान करूंगा, लेकिन हाँ, आप इसे प्रकाशित कोड में नहीं देखना चाहेंगे ... एर्गो: मुझे इसे प्रकाशित करने में शर्म
आएगी

25
वास्तव में, यह आवश्यक नहीं है - विज़ुअल स्टूडियो में आप अपवाद को फेंकने के लिए डिबगर को सेट कर सकते हैं और यह आपके लिए एक इंस्पेक्टर विंडो में अपवाद विवरण लाता है।
jammycakes

8
यदि आप डिबगिंग के दौरान केवल कुछ कोड का उपयोग करना चाहते हैं, तो #if DEBUG ... #endif का उपयोग करें, और आपको इन पंक्तियों को हटाने की आवश्यकता नहीं है
माइकल फ्रीजिम

1
हां, मैंने ऐसा खुद से कई बार किया है। हर अब और फिर एक रिलीज के लिए बच जाएगा। @jammycakes अपवाद पर विजुअल स्टूडियो के टूटने की समस्या है, कभी-कभी मैं जो अपवाद चाहता हूं, वह केवल एक ही नहीं है (या यहां तक ​​कि केवल एक प्रकार का) फेंका जा रहा है। अभी भी "ब्रेक ब्रेक अगर अपवाद द्वारा छोड़ दिया गया" के साथ एक विराम बिंदु स्थिति का पता नहीं है। तब तक, यह उपयोगी रहेगा। माइकल फ्रीजिम: #if DEBUGचारों ओर- try {और } catch () {...}थोड़ा गड़बड़ है और, खुलकर, मुझे चिढ़ाता है ... प्री-प्रोसेसर आमतौर पर बोल रहा है, मेरे दोस्त नहीं।

11

अपवादों को फिर से प्रस्तुत करने का एक वैध कारण यह हो सकता है कि आप अपवाद में जानकारी जोड़ना चाहते हैं, या शायद अपने स्वयं के निर्माण में मूल अपवाद को लपेट सकते हैं:

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) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}

Thanx, yep अपवाद रैपिंग (विशेष रूप से जंजीर) पूरी तरह से समझदार है ... जो नहीं है sane एक अपवाद को पकड़ रहा है, ताकि आप स्टैक ट्रेस को दूर कर सकें, या इससे भी बदतर खा सकते हैं।
कोलेटेक

10

क्या यह बिल्कुल अपवादों को नहीं संभालने के बराबर है?

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


8

आप पूर्व को फेंकना नहीं चाहते हैं - क्योंकि इससे कॉल स्टैक खो जाएगा। अपवाद हैंडलिंग (MSDN) देखें ।

और हाँ, कोशिश ... पकड़ कुछ भी उपयोगी नहीं है (कॉल स्टैक खो के अलावा - इसलिए यह वास्तव में बदतर है - जब तक कि किसी कारण से आप इस जानकारी को उजागर नहीं करना चाहते थे)।


जब आप थ्रो एक्स का उपयोग करते हैं, तो आप पूरी कॉल स्टैक नहीं खोते हैं, आप बस कॉल स्टैक का हिस्सा उस बिंदु से खो देते हैं जहां अपवाद इसकी कॉल स्टैक से अधिक होता है। लेकिन आप कॉल स्टैक को उस विधि से बनाए रखते हैं जो उस अपवाद को नीचे फेंक देता है जहां क्लाइंट ने इसे बुलाया था। वास्तव में ऐसे मामलों का उपयोग किया जा सकता है जहां आप इसका उपयोग करेंगे, अन्यथा Microsoft के अच्छे लोगों ने इसकी अनुमति नहीं दी होगी। उस ने कहा, मैंने इसका उपयोग नहीं किया है। याद करने के लिए एक और मुद्दा यह है कि अपवादों को फेंकना महंगा है। केवल यह एक बहुत ही उचित कारण के लिए करते हैं। लॉगिंग मुझे लगता है कि उचित होगा, आदि
चार्ल्स ओवेन

5

एक बिंदु जो लोगों ने उल्लेख नहीं किया है वह यह है कि जबकि .NET भाषाएँ वास्तव में एक उचित अंतर नहीं बनाती हैं, यह सवाल कि क्या अपवाद होने पर किसी को कार्रवाई करनी चाहिए , और क्या कोई इसे हल करेगा, वास्तव में अलग प्रश्न हैं। ऐसे कई मामले हैं जहां अपवादों के आधार पर कार्रवाई की जानी चाहिए, किसी को भी हल करने की कोई उम्मीद नहीं है, और कुछ ऐसे मामले हैं जहां एक अपवाद को "हल" करने के लिए सभी आवश्यक हैं जो एक निश्चित बिंदु पर स्टैक को खोलना है - आगे कोई कार्रवाई की आवश्यकता नहीं ।

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

अधिकांश .NET भाषाओं में, एक अपवाद के आधार पर कार्रवाई करने के लिए कोड का एकमात्र तरीका catchयह है (भले ही यह जानता हो कि यह अपवाद को हल करने वाला नहीं है), प्रश्न में कार्रवाई करें और फिर- throw)। एक अन्य संभावित दृष्टिकोण यदि कोड इस बात की परवाह नहीं करता है कि okएक try/finallyब्लॉक के साथ एक ध्वज का उपयोग करना क्या अपवाद है ; okध्वज को falseब्लॉक से पहले, और trueब्लॉक से बाहर निकलने से पहले सेट करें , और ब्लॉक returnके भीतर किसी भी समय से पहले । फिर, भीतर finally, मान लें कि यदि okसेट नहीं किया गया है, तो अपवाद होना चाहिए। ऐसा दृष्टिकोण शब्दार्थ catch/ की तुलना में बेहतर है throw, लेकिन बदसूरत है और इसे बनाए रखने की तुलना में कम बनाए रखने योग्य है।


5

यह तब उपयोगी हो सकता है जब आपकी प्रोग्रामिंग किसी लाइब्रेरी या dll के लिए कार्य करती है।

इस रीथ्रो संरचना का उपयोग कॉल स्टैक को उद्देश्यपूर्ण रूप से रीसेट करने के लिए किया जा सकता है ताकि फ़ंक्शन के अंदर किसी व्यक्तिगत फ़ंक्शन से फेंके गए अपवाद को देखने के बजाय, आपको फ़ंक्शन से ही अपवाद मिल जाए।

मुझे लगता है कि यह सिर्फ इसलिए इस्तेमाल किया जाता है ताकि फेंके गए अपवाद साफ-सुथरे हों और लाइब्रेरी की "जड़ों" में न जाएं।


3

कैच-थ्रो का एक संभावित कारण किसी भी अपवाद फिल्टर को स्टैक को नीचे से फ़िल्टर करने से अक्षम करना है ( रैंडम पुराना लिंक )। लेकिन निश्चित रूप से, अगर यही इरादा था, तो वहाँ एक टिप्पणी होगी।


जब तक मैं लिंक नहीं पढ़ता, तब तक आपको वह नहीं मिला ... और मुझे अभी भी यकीन नहीं है कि आप किस बारे में हैं ... मुझे VB.NET के बारे में पूरी तरह से पता नहीं है। मुझे लगता है कि इसका परिणाम "असंगत" होने के योग में है, ठीक है? ... मैं स्थैतिक तरीकों का एक बड़ा प्रशंसक हूं। उनके अलावा सरल होने के बावजूद, यदि आप कोड से विशेषताओं की सेटिंग को अलग करते हैं तो असंगति की संभावना कम है। जो वास्तविक काम करता है। स्टैक "सेल्फ क्लींजिंग" है।
corlettk

3
लोगों को उम्मीद है कि जब वे लिखते हैं "कोशिश {फू ();} अंत में {बार ();}" कि फू और बार के बीच कुछ भी नहीं चलता है। पर ये सच नहीं है; यदि आपके कॉलर ने एक अपवाद फ़िल्टर जोड़ा है, और कोई हस्तक्षेप 'पकड़' नहीं है, और फू () फेंकता है, तो आपके कॉलर से कुछ अन्य यादृच्छिक कोड आपके अंत (बार) के चलने से पहले चलेंगे। यह बहुत बुरा है अगर आपने आक्रमणकारियों या उन्नत सुरक्षा को तोड़ दिया है, यह अपेक्षा करते हुए कि वे अंत तक सामान्य रूप से 'तुरंत' बहाल हो जाएंगे और कोई अन्य कोड अस्थायी परिवर्तन नहीं देखेगा।
ब्रायन

3

यह निर्भर करता है कि आप कैच ब्लॉक में क्या कर रहे हैं, और यदि आप कॉलिंग कोड में त्रुटि पास करना चाहते हैं या नहीं।

आप कह सकते हैं Catch io.FileNotFoundExeption exऔर फिर एक वैकल्पिक फ़ाइल पथ या कुछ ऐसे का उपयोग करें, लेकिन फिर भी त्रुटि को फेंक दें।

इसके Throwबजाय Throw Exआप पूर्ण स्टैक ट्रेस रखने की अनुमति देता है। थ्रो एक्स रीस्ट्स स्टैक ट्रेस थ्रो स्टेटमेंट से निकलता है (मुझे आशा है कि समझ में आता है)।


3

हालांकि कई अन्य उत्तर इस बात के अच्छे उदाहरण प्रदान करते हैं कि आप एक अपवाद को फिर से क्यों पकड़ना चाहते हैं, किसी को भी 'अंततः' परिदृश्य का उल्लेख नहीं लगता है।

इसका एक उदाहरण यह है कि आपके पास एक विधि है जिसमें आप कर्सर सेट करते हैं (उदाहरण के लिए एक प्रतीक्षा कर्सर), विधि में कई निकास बिंदु हैं (जैसे अगर () वापसी;) और आप यह सुनिश्चित करना चाहते हैं कि कर्सर रीसेट है; विधि का अंत।

ऐसा करने के लिए आप सभी कोड को एक कोशिश / पकड़ / अंत में लपेट सकते हैं। अंत में कर्सर को दाहिने कर्सर पर वापस सेट करें। ताकि आप किसी भी वैध अपवाद को न काटें, इसे पकड़ में वापस लाएं।

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}

1
था catchका एक अनिवार्य हिस्सा try...finallyऐतिहासिक दृष्टि से, या यह इस उदाहरण में एक कार्यात्मक भूमिका निभा रहा है? - मैं बस डबल-चेक किया गया हूं, और मैं try {} finally {}बिल्कुल भी कैच ब्लॉक के बिना उपयोग करने में सक्षम हूं ।
सेबी

2

आपके द्वारा पोस्ट किए गए कोड में उदाहरण में, वास्तव में, अपवाद को पकड़ने का कोई मतलब नहीं है क्योंकि पकड़ने पर कुछ भी नहीं किया जाता है, यह सिर्फ फिर से फेंका जाता है, वास्तव में यह कॉल स्टैक खो जाने के बजाय अच्छे से अधिक नुकसान करता है। ।

हालाँकि, आप कुछ अपवाद करने के लिए एक अपवाद को पकड़ सकते हैं (उदाहरण के लिए, फ़ाइल लॉक का sql कनेक्शन बंद करना, या बस कुछ लॉगिंग) अपवाद की स्थिति में इससे निपटने के लिए कॉलिंग कोड पर वापस फेंक दें। यह फ्रंट एंड कोड की तुलना में व्यावसायिक परत में अधिक सामान्य होगा क्योंकि आप अपवाद को संभालने के लिए कोडर को अपनी व्यावसायिक परत को लागू कर सकते हैं।

फिर से पुनरावृति करने के लिए हालांकि आपके द्वारा पोस्ट किए गए उदाहरण में अपवाद को पकड़ने का कोई मतलब नहीं है। ऐसा नहीं है!


1

क्षमा करें, लेकिन "बेहतर डिज़ाइन" के रूप में कई उदाहरण अभी भी बुरी तरह से गंध करते हैं या बेहद भ्रामक हो सकते हैं। {} कैच {लॉग; फेंक} बस पूरी तरह से व्यर्थ है। आवेदन के अंदर अपवाद लॉगिंग केंद्रीय स्थान पर किया जाना चाहिए। अपवाद स्टैकट्रेस को वैसे भी बबल करते हैं, क्यों न उन्हें कहीं लॉग अप किया जाए और सिस्टम की सीमाओं के करीब?

सावधानी का उपयोग तब किया जाना चाहिए जब आप अपने संदर्भ (यानी किसी एक उदाहरण में डीटीओ) को क्रमबद्ध करते हैं, बस लॉग संदेश में। इसमें आसानी से संवेदनशील जानकारी हो सकती है जो सभी लोगों के हाथों तक नहीं पहुंचना चाहता है जो लॉग फ़ाइलों तक पहुंच सकते हैं। और यदि आप अपवाद में कोई नई जानकारी नहीं जोड़ते हैं, तो मैं वास्तव में अपवाद के बिंदु को नहीं देखता हूं। अच्छे पुराने जावा के पास इसके लिए कुछ बिंदु हैं, यह जानने के लिए कॉलर की आवश्यकता होती है कि किस तरह के अपवादों की अपेक्षा करनी चाहिए फिर कोड को कॉल करना। चूंकि आपके पास .NET में यह नहीं है, इसलिए मैंने जिन मामलों को देखा है उनमें से कम से कम 80% पर रैपिंग कोई अच्छा काम नहीं करती है।


आपके विचार जो के लिए धन्यवाद। जावा (और C # में, मुझे लगता है) मैं एक वर्ग-स्तरीय एनोटेशन @FaultBoundary देखना पसंद करूंगा जो सभी अपवादों (अनियंत्रित अपवाद-प्रकारों सहित) को पकड़ने या घोषित-से-फेंके जाने के लिए मजबूर करता है। मैं प्रत्येक वास्तु परत के सार्वजनिक इंटरफेस पर इस एनोटेशन का उपयोग करूंगा। इसलिए @FaultBoundary ThingDAO इंटरफ़ेस कार्यान्वयन विवरणों जैसे कि SQLException, NPE's, या AIOB's को लीक करने में सक्षम नहीं होगा। इसके बजाय "कारण" स्टैकट्रेस को लॉग किया जाएगा और एक DAOSystemException को फेंक दिया जाएगा ... मैं सिस्टम अपवाद को "स्थायी रूप से घातक" के रूप में परिभाषित करता हूं।
corlettk

5
पकड़ने, लॉग करने, फिर रेथ्रो करने के बहुत सारे कारण हैं। विशेष रूप से यदि कैच लॉग के साथ विधि की जानकारी है कि आप एक बार खो देते हैं तो आप विधि से बाहर हो जाते हैं। त्रुटि को बाद में संभाला जा सकता है लेकिन लॉग नहीं किया गया है, और आपने सिस्टम में दोषों के बारे में जानकारी खो दी है।
एंडी

1
यह वह जगह है जहां अपवाद वर्ग की डेटा संपत्ति काम है - सामान्य लॉगिंग के लिए स्थानीय जानकारी को कैप्चर करना। यह लेख मूल रूप से मेरे ध्यान में लाया गया: blog.abodit.com/2010/03/…
McGuireV10

1

दूसरों ने जो कहा है, इसके अलावा, एक संबंधित प्रश्न के मेरे उत्तर को देखें जो दर्शाता है कि पकड़ना और पुन: डूबना एक नो-ऑप है (यह VB में है, लेकिन कुछ कोड VB से C # मंगवाए जा सकते हैं)।


हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - समीक्षा से
LHIOUI

@ HamzaLH, मैं मानता हूं कि यह एक अच्छा लिखित उत्तर नहीं है, लेकिन इसमें जानकारी है, अन्य उत्तरों और सकारात्मक वोटों के लिए अलग है। तो मुझे समझ में नहीं आता, आप इसे हटाने का सुझाव क्यों देते हैं? "लघु उत्तर जो विषय पर हैं और समाधान देते हैं, अभी भी उत्तर हैं।" से meta.stackexchange.com/questions/226258/...
माइकल Freidgeim

यह केवल लिंक का उत्तर है
LHIOUI

1. लिंक-केवल उत्तरों को टिप्पणियों में बदलना चाहिए, हटाए नहीं। 2. यह अन्य एसओ प्रश्न का संदर्भ है, बाहरी साइट के लिए नहीं, जिसे समय के साथ टूटने की संभावना कम माना जाता है। 3. इसमें कुछ अतिरिक्त विवरण हैं, जो इसे "केवल लिंक नहीं" बनाते हैं
माइकल फ्रीजिम

1

परिदृश्य कैच-लॉग-रीथ्रो के बारे में बात करने वाले अधिकांश उत्तर।

अपने कोड में इसे लिखने के बजाय, विशेष रूप से Postharp.Diagnostic.Toolkit के साथ OnExceptionOptions के साथ AOP का उपयोग करने पर विचार करें।


हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - समीक्षा से
टोनी डोंग

@ टोनीडॉन्ग, मैं मानता हूं कि यह एक अच्छा लिखित उत्तर नहीं है, लेकिन इसमें जानकारी है, अन्य उत्तरों और सकारात्मक वोटों के लिए अलग है। तो मुझे समझ में नहीं आता, आप इसे हटाने का सुझाव क्यों देते हैं? BTW, लिंक 5 साल बाद भी मान्य है। "लघु उत्तर जो विषय पर हैं और समाधान देते हैं, अभी भी उत्तर हैं।" से meta.stackexchange.com/questions/226258/...
माइकल Freidgeim

Stackoverflow का केवल यही सुझाव है।
टोनी डोंग

@ टोनीडोंग, यदि उत्तर बिल्कुल बेकार नहीं है, तो आपको "लुक ओके" चुनना चाहिए
माइकल फ्रीजिम

0

throwजब आप वर्तमान अपवादों को संभालने के लिए कोई विशेष कोड नहीं रखते हैं, या ऐसे मामलों में जब आप विशिष्ट त्रुटि मामलों को संभालने के लिए तर्क रखते हैं, लेकिन अन्य सभी को छोड़ना चाहते हैं, तब अपवादों को हटाना उपयोगी है।

उदाहरण:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

हालांकि, इसे पकड़ने का एक और तरीका है, कैच ब्लॉक में सशर्त खंड का उपयोग करना :

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

.NET रनटाइम के अपवाद को फिर से फेंकने की तुलना में यह तंत्र अधिक कुशल है, इसे फेंकने से पहले अपवाद ऑब्जेक्ट को फिर से बनाना नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.