C # में, वेरिएबल्स को ट्रायल ब्लॉक के दायरे में सीमित घोषित क्यों किया जाता है?


23

मैं इसमें त्रुटि हैंडलिंग जोड़ना चाहता हूं:

var firstVariable = 1;
var secondVariable = firstVariable;

नीचे संकलन नहीं होगा:

try
{
   var firstVariable = 1;
}
catch {}

try
{
   var secondVariable = firstVariable;
}
catch {}

अन्य कोड ब्लॉक के रूप में चर के दायरे को प्रभावित करने के लिए एक कोशिश पकड़ ब्लॉक के लिए क्यों आवश्यक है? संगति-एक तरफ, क्या यह समझ में नहीं आता कि हमारे कोड को रिफलेक्टर की आवश्यकता के बिना त्रुटि से निपटने में सक्षम होना चाहिए?


14
A try.. catchएक विशिष्ट प्रकार का कोड ब्लॉक है, और जहाँ तक सभी कोड ब्लॉक जाते हैं, आप एक वेरिएबल को एक में घोषित नहीं कर सकते हैं और उस वैरिएबल को दूसरे स्कोप के रूप में उपयोग कर सकते हैं।
नील

"एक विशिष्ट प्रकार का कोड ब्लॉक है"। किस तरह से विशिष्ट? धन्यवाद
JᴀʏMᴇᴇ

7
मेरा मतलब है कि घुंघराले कोष्ठक के बीच कुछ भी एक कोड ब्लॉक है। आप इसे एक if स्टेटमेंट के बाद और स्टेटमेंट के लिए फॉलो करते हुए देखते हैं, हालांकि कॉन्सेप्ट एक ही है। सामग्री अपने मूल क्षेत्र के संबंध में एक ऊंचे दायरे में है। मुझे पूरा यकीन है कि यह समस्याग्रस्त होगा यदि आप {}बिना कोशिश किए घुंघराले कोष्ठक का उपयोग करते हैं।
नील

युक्ति: ध्यान दें कि (IDisposable) {} और सिर्फ {} का उपयोग करना भी इसी तरह लागू होता है। जब आप किसी आईडीसोप्रेट के साथ प्रयोग करते हैं, तो यह सफलता या विफलता की परवाह किए बिना संसाधनों को स्वचालित रूप से साफ कर देगा। इसके कुछ अपवाद हैं, जैसे कि आप उन सभी वर्गों से अपेक्षा नहीं करेंगे जिन्हें आप आईडीसोप्लिक लागू करेंगे ...
जूलिया मैक्गिवेन

1
StackOverflow पर इसी सवाल पर बहुत चर्चाएँ, यहाँ: stackoverflow.com/questions/94977/…
जॉन श्नाइडर

जवाबों:


90

क्या होगा अगर आपका कोड था:

try
{
   MethodThatMightThrow();
   var firstVariable = 1;
}
catch {}

try
{
   var secondVariable = firstVariable;
}
catch {}

अब आप एक अघोषित चर ( firstVariable) का उपयोग करने की कोशिश कर रहे हैं यदि आपकी विधि कॉल फेंकता है।

नोट : उपरोक्त उदाहरण विशेष रूप से मूल प्रश्न का उत्तर देता है, जिसमें कहा गया है कि "स्थिरता-एक तरफ"। यह दर्शाता है कि स्थिरता के अलावा अन्य कारण हैं। लेकिन जैसा कि पीटर के जवाब से पता चलता है, निरंतरता से एक शक्तिशाली तर्क भी है, जो निश्चित रूप से निर्णय में एक बहुत महत्वपूर्ण कारक होगा।


आह, यह वही है जो मैं था। मुझे पता था कि कुछ भाषा सुविधाएँ थीं, जो मुझे असंभव बनाने का सुझाव दे रही थीं, लेकिन मैं किसी भी परिदृश्य के साथ नहीं आ सकता था। बहुत बहुत धन्यवाद।
J --Mᴇᴇ

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

3
सी # जैसी स्थिर भाषा के लिए, घोषणा केवल संकलन समय पर ही प्रासंगिक है। कंपाइलर घोषणा को आसानी से दायरे में ले जा सकता है। रनटाइम पर अधिक महत्वपूर्ण तथ्य यह है कि चर को प्रारंभ नहीं किया जा सकता है
jpmc26

3
मैं इस जवाब से असहमत हूं। C # में पहले से ही नियम है कि कुछ डेटाफ्लो जागरूकता के साथ, अनइंस्टॉल किए गए चर को नहीं पढ़ा जा सकता है। ( switchअन्य लोगों के मामले में चर घोषित करने और उन्हें दूसरों तक पहुंचाने की कोशिश करें ।) यह नियम आसानी से यहां लागू हो सकता है और इस कोड को वैसे भी संकलित करने से रोक सकता है। मुझे लगता है कि नीचे पीटर का उत्तर अधिक प्रशंसनीय है।
सेबस्टियन रेडल

2
अघोषित रूप से अघोषित रूप से अंतर है और C # उन्हें अलग से ट्रैक करता है। यदि आपको ब्लॉक के बाहर एक चर का उपयोग करने की अनुमति दी गई थी, जहां यह घोषित किया गया था, तो इसका मतलब है कि आप इसे पहले catchब्लॉक में असाइन कर पाएंगे और फिर इसे निश्चित रूप से दूसरे tryब्लॉक में सौंपा जाएगा ।
svick

64

मुझे पता है कि यह बेन द्वारा अच्छी तरह से उत्तर दिया गया है, लेकिन मैं उस स्थिरता पीओवी को संबोधित करना चाहता था जिसे आसानी से एक तरफ धकेल दिया गया था। यह मानते हुए कि try/catchब्लॉक स्कोप को प्रभावित नहीं करते हैं, तो आप इसके साथ समाप्त हो जाएंगे:

{
    // new scope here
}

try
{
   // Not new scope
}

और यह मेरे लिए में पर सिर दुर्घटनाओं से कम विस्मय (POLA) के सिद्धांत क्योंकि आप अब {और }क्या उन्हें पहले की संदर्भ के आधार पर दोहरा काम कर रही है।

इस झंझट से बाहर निकलने का एकमात्र तरीका कुछ अन्य मार्करों को डेलीनेट try/catchब्लॉक करना है। जो एक कोड गंध जोड़ने के लिए शुरू होता है। इसलिए जब तक आप try/catchभाषा में नहीं आते , तब तक यह गड़बड़ हो जाती थी कि आप स्कॉप्ड संस्करण के साथ बेहतर हो जाते थे।


एक और बेहतरीन जवाब। और मैंने पोला के बारे में कभी नहीं सुना, इतना अच्छा आगे पढ़ रहा हूं। बहुत बहुत धन्यवाद दोस्त।
J --Mᴇᴇ

"इस झंझट से बाहर निकलने का एकमात्र तरीका कुछ अन्य मार्करों को सीमांकित try/ catchब्लॉक करना है।" - क्या आपका मतलब है try { { // scope } }:? :)
कॉम्पिटिशन

@CompuChip है कि {}दायरे के रूप में डबल ड्यूटी खींचना होगा और अभी भी संदर्भ के आधार पर गुंजाइश नहीं बना रहा है। try^ //no-scope ^एक अलग मार्कर का एक उदाहरण होगा।
Leliel

1
मेरी राय में, यह बहुत अधिक मौलिक कारण है, और "वास्तविक" उत्तर के करीब है।
जैक एडले

@JackAidley खासकर जब से आप पहले से ही कोड लिख सकते हैं जहां आप एक चर का उपयोग करते हैं जिसे असाइन नहीं किया जा सकता है। इसलिए जब बेन के जवाब में एक बिंदु है कि यह कैसे उपयोगी व्यवहार है, तो मैं इसे नहीं देखता कि यह व्यवहार क्यों मौजूद है। बेन का जवाब ओपी को यह कहते हुए ध्यान देता है कि "स्थिरता की खातिर", लेकिन निरंतरता एक पूरी तरह से ठीक कारण है! संकीर्ण दायरे में सभी प्रकार के अन्य लाभ हैं।
कैट

21

संगति-एक तरफ, क्या यह समझ में नहीं आता कि हमारे कोड को रिफलेक्टर की आवश्यकता के बिना त्रुटि से निपटने में सक्षम होना चाहिए?

इसका उत्तर देने के लिए, केवल एक चर के दायरे को देखना आवश्यक है

यहां तक ​​कि अगर चर दायरे में रहता है, तो भी इसे निश्चित रूप से नहीं सौंपा जाएगा

ट्रायल ब्लॉक में वैरिएबल को डिक्लेयर करना - कंपाइलर को, और ह्यूमन रीडर्स को - कि यह उस ब्लॉक के अंदर ही सार्थक है। संकलक के लिए यह लागू करना उपयोगी है।

यदि आप चाहते हैं कि ट्रायल ब्लॉक के बाद वैरिएबल गुंजाइश में हो, तो आप इसे ब्लॉक के बाहर घोषित कर सकते हैं:

var zerothVariable = 1_000_000_000_000L;
int firstVariable;

try {
    // Change checked to unchecked to allow the overflow without throwing.
    firstVariable = checked((int)zerothVariable);
}
catch (OverflowException e) {
    Console.Error.WriteLine(e.Message);
    Environment.Exit(1);
}

यह व्यक्त करता है कि चर कोशिश ब्लॉक के बाहर सार्थक हो सकता है। संकलक यह अनुमति देगा।

लेकिन यह एक और कारण भी दिखाता है कि आमतौर पर एक कोशिश ब्लॉक में उन्हें पेश करने के बाद चर को दायरे में रखना उपयोगी नहीं होगा। C # कंपाइलर निश्चित असाइनमेंट विश्लेषण करता है और एक वैरिएबल के मूल्य को पढ़ने पर रोक लगाता है, जो यह साबित नहीं हुआ है कि उसे एक मान दिया गया है। तो आप अभी भी चर से नहीं पढ़ सकते हैं।

मान लीजिए कि मैं प्रयास खंड के बाद चर से पढ़ने का प्रयास करता हूं:

Console.WriteLine(firstVariable);

यह एक संकलन-समय त्रुटि देगा :

CS0165 अप्रभावित स्थानीय चर 'FirstVariable' का उपयोग

मैंने एनवायरनमेंट को कॉल किया। कैच ब्लॉक में, इसलिए मुझे पता है कि वेरिएबल को Console.WriteLine पर कॉल करने से पहले असाइन किया गया है। लेकिन संकलक यह अनुमान नहीं लगाता है।

कंपाइलर इतना सख्त क्यों है?

मैं यह भी नहीं कर सकता:

int n;

try {
    n = 10; // I know this won't throw an IOException.
}
catch (IOException) {
}

Console.WriteLine(n);

इस प्रतिबंध को देखने का एक तरीका यह है कि C # में निश्चित असाइनमेंट विश्लेषण बहुत परिष्कृत नहीं है। लेकिन इसे देखने का एक और तरीका यह है कि, जब आप कैच क्लॉस के साथ एक कोशिश ब्लॉक में कोड लिखते हैं, तो आप संकलक और किसी भी मानव पाठक दोनों को बता रहे हैं कि इसे ऐसे व्यवहार किया जाना चाहिए जैसे यह सब नहीं चल सकता।

यह समझने के लिए कि मेरा क्या मतलब है, कल्पना करें कि कंपाइलर ने ऊपर दिए गए कोड को अनुमति दी है, लेकिन फिर आपने कोशिश ब्लॉक में एक फ़ंक्शन में एक कॉल जोड़ा है जिसे आप व्यक्तिगत रूप से जानते हैं कि कोई अपवाद नहीं होगा । यह सुनिश्चित करने में सक्षम नहीं होने के कारण कि फंक्शन को ए फेक नहीं किया गया है IOException, कंपाइलर को पता नहीं चल सकता है कि nअसाइन किया गया था, और फिर आपको रिफ्लेक्टर करना होगा।

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

आप यह सुनिश्चित कर सकते हैं कि चर को सभी कोड पथों के माध्यम से सौंपा गया है।

आप चर को कोशिश ब्लॉक से पहले या कैच ब्लॉक में मान देकर संकलित कर सकते हैं। इस तरह, यह अभी भी आरंभीकृत या नियत किया गया होगा, भले ही कोशिश ब्लॉक में असाइनमेंट न हो। उदाहरण के लिए:

var n = 0; // But is this meaningful, or just covering a bug?

try {
    n = 10;
}
catch (IOException) {
}

Console.WriteLine(n);

या:

int n;

try {
    n = 10;
}
catch (IOException) {
    n = 0; // But is this meaningful, or just covering a bug?
}

Console.WriteLine(n);

वो संकलन। लेकिन केवल कुछ ऐसा करना सबसे अच्छा है यदि आप जो डिफ़ॉल्ट मान देते हैं वह समझ में आता है * और सही व्यवहार पैदा करता है।

ध्यान दें, इस दूसरे मामले में जहां आप कोशिश ब्लॉक में और सभी कैच ब्लॉक में वेरिएबल असाइन करते हैं, हालांकि आप ट्राइ-कैच के बाद वेरिएबल को पढ़ सकते हैं, फिर भी आप अटैच finallyब्लॉक के अंदर वेरिएबल नहीं पढ़ पाएंगे , क्योंकि निष्पादन अधिक स्थितियों में एक कोशिश ब्लॉक को छोड़ सकता है जितना हम अक्सर सोचते हैं

* वैसे, कुछ भाषाएं, जैसे C और C ++, दोनों ही असिंचित चर की अनुमति देती हैं और उनमें पढ़ने से रोकने के लिए निश्चित असाइनमेंट विश्लेषण नहीं है। चूँकि एकतरफा स्मृति को पढ़ने से प्रोग्रामों के प्रति उदासीनता और अनिश्चिततापूर्ण व्यवहार होता है, इसलिए आमतौर पर उन भाषाओं में वैरिएबल शुरू करने से बचने की सिफारिश की जाती है, बिना इनिशलाइज़र की आपूर्ति के। C # और Java जैसे निश्चित असाइनमेंट विश्लेषण वाली भाषाओं में, कंपाइलर आपको अनइंस्टॉल किए गए वैरिएबल को पढ़ने से बचाता है और साथ ही उन्हें अर्थहीन मान के साथ शुरू करने की कम बुराई से बचाता है जिसे बाद में अर्थपूर्ण समझा जा सकता है।

आप इसे इतना कोड पथ बना सकते हैं जहां चर को एक अपवाद (या वापसी) नहीं दिया जाता है।

यदि आप कुछ कार्रवाई करने (लॉगिंग की तरह) करने की कोशिश करते हैं और अपवाद को फिर से उखाड़ फेंकते हैं या किसी अन्य अपवाद को फेंक देते हैं, और यह किसी भी कैच क्लॉस में होता है जहां चर नहीं सौंपा गया है, तो कंपाइलर को पता चलेगा कि चर सौंपा गया है:

int n;

try {
    n = 10;
}
catch (IOException e) {
    Console.Error.WriteLine(e.Message);
    throw;
}

Console.WriteLine(n);

वह संकलन करता है, और अच्छी तरह से एक उचित विकल्प हो सकता है। हालांकि, एक वास्तविक आवेदन में, जब तक अपवाद केवल में फेंक दिया जाता है स्थितियों में, जहां यह और भी मतलब नहीं है ठीक करने के लिए प्रयास करने के लिए * , आप यह सुनिश्चित करें कि आप अभी भी पकड़ने रहे हैं बनाना चाहिए और ठीक से यह निपटने कहीं

(आप इस स्थिति में किसी अंतिम ब्लॉक में चर को नहीं पढ़ सकते हैं, लेकिन ऐसा महसूस नहीं होता है कि आपको ऐसा करने में सक्षम होना चाहिए - आखिरकार, अंततः ब्लॉक हमेशा अनिवार्य रूप से चलते हैं, और इस मामले में चर हमेशा असाइन नहीं किया जाता है ।)

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

हो सकता है कि आप वास्तव में कोड को रिफलेक्टर करना चाहते हों।

अपने उदाहरण में, आप परिचय firstVariableऔर secondVariableकोशिश ब्लॉकों में। जैसा कि मैंने कहा है, आप उन्हें कोशिश कर सकते हैं इससे पहले कि वे असाइन किए गए ब्लॉकों को ब्लॉक करें, ताकि वे बाद में दायरे में रहें, और आप कंपाइलर को संतुष्ट / छल कर सकते हैं ताकि आप उन्हें हमेशा सुनिश्चित कर सकें कि वे हमेशा असाइन किए गए हैं।

लेकिन उन ब्लॉकों के बाद दिखाई देने वाला कोड संभवतः उन पर निर्भर करता है जिन्हें सही तरीके से सौंपा गया है। यदि ऐसा है, तो आपके कोड को प्रतिबिंबित करना चाहिए और यह सुनिश्चित करना चाहिए।

सबसे पहले, आप (और) को वास्तव में वहाँ त्रुटि को संभालना चाहिए? अपवादों को संभालने का एक कारण यह है कि त्रुटियों को संभालना आसान बनाने के लिए जहां वे प्रभावी ढंग से निपट सकते हैं , भले ही वह पास न हो जहां वे होते हैं।

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

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

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

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

उदाहरण के लिए, मान लीजिए कि आप किसी भी चर को असाइन करने में विफलता पर आवेदन तुरंत छोड़ना चाहते हैं। (स्पष्ट रूप से सभी अपवाद हैंडलिंग घातक त्रुटियों के लिए नहीं है; यह सिर्फ एक उदाहरण है, और हो सकता है कि आप इस समस्या पर प्रतिक्रिया के लिए अपना आवेदन कैसे चाहते हैं।) आप ऐसा कुछ कर सकते हैं।

// In real life, this should be named more descriptively.
private static (int firstValue, int secondValue) GetFirstAndSecondValues()
{
    try {
        // This code is contrived. The idea here is that obtaining the values
        // could actually fail, and throw a SomeSpecificException.
        var firstVariable = 1;
        var secondVariable = firstVariable;
        return (firstVariable, secondVariable);
    }
    catch (SomeSpecificException e) {
        Console.Error.WriteLine(e.Message);
        Environment.Exit(1);
        throw new InvalidOperationException(); // unreachable
    }
}

// ...and of course so should this.
internal static void MethodThatUsesTheValues()
{
    var (firstVariable, secondVariable) = GetFirstAndSecondValues();

    // Code that does something with them...
}

यह कोड रिटर्न करता है और कई मानों को वापस करने के लिए C # 7.0 के सिंटैक्स के साथ एक वैल्यूटल को डिकंस्ट्रक्ट करता है, लेकिन यदि आप अभी भी C # के पुराने संस्करण पर हैं, तो भी आप इस तकनीक का उपयोग कर सकते हैं; उदाहरण के लिए, आप मापदंडों का उपयोग कर सकते हैं, या एक कस्टम ऑब्जेक्ट वापस कर सकते हैं जो दोनों मान प्रदान करता है । इसके अलावा, यदि दो चर वास्तव में कसकर संबंधित नहीं हैं, तो संभवतः दो अलग-अलग तरीकों का उपयोग करना बेहतर होगा

खासकर यदि आपके पास कई तरीके हैं, तो आपको अपने कोड को घातक त्रुटियों के उपयोगकर्ता को सूचित करने और छोड़ने के लिए केंद्रीयकरण पर विचार करना चाहिए। (उदाहरण के लिए, यदि आप एक लिख सकता है Dieएक साथ विधि messageपैरामीटर।) पंक्ति वास्तव में मार डाला कभी नहीं किया गया है , ताकि आप की जरूरत नहीं है (और नहीं होना चाहिए) इसके लिए एक पकड़ खंड लिखें।throw new InvalidOperationException();

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

निष्कर्ष: स्कोप तस्वीर का केवल एक हिस्सा है।

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


"जब आप कैच क्लॉस के साथ एक कोशिश ब्लॉक में कोड लिखते हैं, तो आप संकलक और किसी भी मानव पाठक दोनों से कह रहे हैं कि इसे ऐसे व्यवहार किया जाना चाहिए जैसे यह सब नहीं चल सकता है।" संकलक के बारे में क्या परवाह है कि नियंत्रण बाद के बयानों तक पहुंच सकता है, भले ही पिछले बयान एक अपवाद को फेंक दें। कंपाइलर आम तौर पर मानता है कि यदि एक स्टेटमेंट एक अपवाद फेंकता है, तो अगले स्टेटमेंट को निष्पादित नहीं किया जाएगा, इसलिए अनसाइन किए गए वेरिएबल को नहीं पढ़ा जाएगा। एक 'कैच' जोड़ने से बाद के स्टेटमेंट तक कंट्रोल पहुंच सकेगा - यह वह कैच है जो मायने रखता है, न कि यह कि क्या ट्राइ ब्लॉक में कोड फेंकता है।
पीट किर्कम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.