खोज…
टिप्पणियों
सम्बंधित:
एक अपवाद को पकड़ने
असाधारण परिस्थितियों में कोड कर सकते हैं और अपवादों को फेंक देना चाहिए। इसके उदाहरणों में शामिल हैं:
- एक धारा के अंत में अतीत को पढ़ने का प्रयास
- किसी फ़ाइल तक पहुँचने के लिए आवश्यक अनुमतियां नहीं हैं
- अमान्य ऑपरेशन करने का प्रयास करना, जैसे कि शून्य से विभाजित करना
- इंटरनेट से किसी फ़ाइल को डाउनलोड करते समय होने वाला एक समयबाह्य
कॉल करने वाला इन अपवादों को "पकड़" कर उन्हें संभाल सकता है, और ऐसा तभी करना चाहिए जब:
- यह वास्तव में असाधारण परिस्थितियों को हल कर सकता है या उचित रूप से पुनर्प्राप्त कर सकता है, या;
- यह अपवाद को अतिरिक्त संदर्भ प्रदान कर सकता है जो तब उपयोगी होगा जब अपवाद को फिर से फेंकने की आवश्यकता हो (पुन: फेंके गए अपवाद अपवाद संचालकों द्वारा कॉल स्टैक को और पकड़ा जाए)
यह ध्यान दिया जाना चाहिए कि अपवाद को पकड़ने के लिए नहीं चुनना पूरी तरह से वैध है अगर इरादा इसके लिए एक उच्च स्तर पर संभाला जाए।
अपवाद को पकड़ने का try { ... }
ब्लॉक में संभावित-फेंकने वाले कोड को रैप करके किया जाता है, और निम्न अपवादों को पकड़कर इसे पकड़ने में सक्षम है catch (ExceptionType) { ... }
ब्लॉक:
Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();
Stream fileStream;
try
{
fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
Console.WriteLine("File '{0}' could not be found.", filename);
}
अंत में ब्लॉक का उपयोग करना
finally { ... }
एक try-finally
या try-catch-finally
में हमेशा निष्पादित करेगा, भले ही कोई अपवाद हुआ हो या नहीं (सिवाय इसके कि जब StackOverflowException
को फेंका गया हो या कॉल किया गया हो, तो Environment.FailFast()
)।
इसे सुरक्षित रूप से try { ... }
ब्लॉक में प्राप्त संसाधनों को मुक्त या साफ करने के लिए उपयोग किया जा सकता है।
Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();
Stream fileStream = null;
try
{
fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
if (fileStream != null)
{
fileStream.Dispose();
}
}
कैच और पुनर्विचार ने अपवादों को पकड़ा
जब आप एक अपवाद को पकड़ना चाहते हैं और कुछ करना चाहते हैं, लेकिन आप कोड के वर्तमान ब्लॉक के निष्पादन को जारी नहीं रख सकते हैं, तो अपवाद के कारण, आप कॉल स्टैक में अगले अपवाद हैंडलर के अपवाद को फिर से हटाना चाह सकते हैं। ऐसा करने के अच्छे तरीके और बुरे तरीके हैं।
private static void AskTheUltimateQuestion()
{
try
{
var x = 42;
var y = x / (x - x); // will throw a DivideByZeroException
// IMPORTANT NOTE: the error in following string format IS intentional
// and exists to throw an exception to the FormatException catch, below
Console.WriteLine("The secret to life, the universe, and everything is {1}", y);
}
catch (DivideByZeroException)
{
// we do not need a reference to the exception
Console.WriteLine("Dividing by zero would destroy the universe.");
// do this to preserve the stack trace:
throw;
}
catch (FormatException ex)
{
// only do this if you need to change the type of the Exception to be thrown
// and wrap the inner Exception
// remember that the stack trace of the outer Exception will point to the
// next line
// you'll need to examine the InnerException property to get the stack trace
// to the line that actually started the problem
throw new InvalidOperationException("Watch your format string indexes.", ex);
}
catch (Exception ex)
{
Console.WriteLine("Something else horrible happened. The exception: " + ex.Message);
// do not do this, because the stack trace will be changed to point to
// this location instead of the location where the exception
// was originally thrown:
throw ex;
}
}
static void Main()
{
try
{
AskTheUltimateQuestion();
}
catch
{
// choose this kind of catch if you don't need any information about
// the exception that was caught
// this block "eats" all exceptions instead of rethrowing them
}
}
आप अपवाद प्रकार और यहां तक कि अपवाद गुणों द्वारा फ़िल्टर कर सकते हैं (C # 6.0 में नया, VB.NET में थोड़ा अधिक उपलब्ध है (आवश्यक उद्धरण):
अपवाद फ़िल्टर
चूंकि सी # 6.0 अपवादों को when
ऑपरेटर का उपयोग करके फ़िल्टर किया जा सकता है।
यह एक सरल का उपयोग कर के समान है if
लेकिन स्टैक नहीं करता है तो अंदर हालत when
पूरा नहीं होता है।
उदाहरण
try
{
// ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
// ...
}
सी # 6.0 सुविधाओं में एक ही जानकारी यहां मिल सकती है: अपवाद फ़िल्टर
कैच ब्लॉक में अपवाद को रोकना
एक catch
ब्लॉक के भीतर throw
कीवर्ड का उपयोग अपने आप ही किया जा सकता है, बिना किसी अपवाद मूल्य को निर्दिष्ट किए, उस अपवाद को फिर से उखाड़ throw
लिए जो अभी पकड़ा गया था। एक अपवाद को रोकना मूल अपवाद को अपवाद हैंडलिंग श्रृंखला को जारी रखने की अनुमति देता है, इसके कॉल स्टैक या संबंधित डेटा को संरक्षित करना:
try {...}
catch (Exception ex) {
// Note: the ex variable is *not* used
throw;
}
एक सामान्य एंटी-पैटर्न इसके बजाय throw ex
, जिसमें स्टैक ट्रेस के अगले अपवाद हैंडलर के दृश्य को सीमित करने का प्रभाव है:
try {...}
catch (Exception ex) {
// Note: the ex variable is thrown
// future stack traces of the exception will not see prior calls
throw ex;
}
सामान्य रूप से throw ex
का उपयोग करना वांछनीय नहीं है, क्योंकि भविष्य के अपवाद हैंडलर जो स्टैक ट्रेस का निरीक्षण करते हैं, केवल कॉल को वापस throw ex
सक्षम होंगे। ex
चर को छोड़ कर, और केवल throw
कीवर्ड का उपयोग करके मूल अपवाद "बबल-अप" होगा ।
इसकी जानकारी को संरक्षित करते हुए एक अलग विधि से एक अपवाद को फेंकना
कभी-कभी आप एक अपवाद को पकड़ना चाहते हैं और मूल अपवाद स्टैक को संरक्षित करते हुए इसे अलग थ्रेड या विधि से फेंकना चाहते हैं। यह ExceptionDispatchInfo
साथ किया जा सकता है:
using System.Runtime.ExceptionServices;
void Main()
{
ExceptionDispatchInfo capturedException = null;
try
{
throw new Exception();
}
catch (Exception ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
Foo(capturedException);
}
void Foo(ExceptionDispatchInfo exceptionDispatchInfo)
{
// Do stuff
if (capturedException != null)
{
// Exception stack trace will show it was thrown from Main() and not from Foo()
exceptionDispatchInfo.Throw();
}
}