"पकड़ने" या "आखिर" में गुंजाइश में "प्रयास" में घोषित चर क्यों नहीं हैं?


139

C # में और जावा में (और संभवतः अन्य भाषाओं में भी), "कोशिश" ब्लॉक में घोषित चर इसी "पकड़" या "अंत में" ब्लॉक के दायरे में नहीं हैं। उदाहरण के लिए, निम्नलिखित कोड संकलित नहीं करता है:

try {
  String s = "test";
  // (more code...)
}
catch {
  Console.Out.WriteLine(s);  //Java fans: think "System.out.println" here instead
}

इस कोड में, कैच ब्लॉक में s के संदर्भ में एक संकलन-टाइम त्रुटि उत्पन्न होती है, क्योंकि s केवल कोशिश ब्लॉक में स्कोप है। (जावा में, संकलन त्रुटि "s हल नहीं की जा सकती है", C # में, यह "s 'वर्तमान संदर्भ में मौजूद नहीं है"।)

इस समस्या का सामान्य हल ट्रायल ब्लॉक के बजाय वेरिएबल्स को ट्राइ ब्लॉक से ठीक पहले घोषित करना प्रतीत होता है:

String s;
try {
  s = "test";
  // (more code...)
}
catch {
  Console.Out.WriteLine(s);  //Java fans: think "System.out.println" here instead
}

हालांकि, कम से कम मेरे लिए, (1) यह एक क्लंकी समाधान की तरह लगता है, और (2) इसका परिणाम उन प्रोग्रामर में होता है, जो प्रोग्रामर के इरादे से बड़ा स्कोप होता है (केवल विधि के पूरे शेष, केवल संदर्भ में कोशिश-पकड़ने-अंत में)।

मेरा सवाल है, इस भाषा डिजाइन निर्णय (जावा में, सी # में, और / या किसी अन्य लागू भाषाओं में) के पीछे तर्क क्या हैं?

जवाबों:


171

दो चीज़ें:

  1. आम तौर पर, जावा में स्कोप के सिर्फ 2 स्तर होते हैं: ग्लोबल और फंक्शन। लेकिन, कोशिश / पकड़ एक अपवाद है (कोई सज़ा नहीं)। जब एक अपवाद को फेंक दिया जाता है और अपवाद वस्तु को एक चर दिया जाता है, तो वह वस्तु चर केवल "कैच" सेक्शन के भीतर उपलब्ध होता है और जैसे ही कैच पूरा होता है, नष्ट हो जाता है।

  2. (और अधिक महत्वपूर्ण बात)। आप यह नहीं जान सकते हैं कि कोशिश ब्लॉक में अपवाद कहां फेंका गया था। हो सकता है कि यह आपके चर घोषित होने से पहले हो। इसलिए यह कहना असंभव है कि कैच / अंत में क्लॉज के लिए कौन से चर उपलब्ध होंगे। निम्नलिखित मामले पर विचार करें, जहाँ आपको सुझाव दिया गया है:

    
    try
    {
        throw new ArgumentException("some operation that throws an exception");
        string s = "blah";
    }
    catch (e as ArgumentException)
    {  
        Console.Out.WriteLine(s);
    }

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


55

आप यह कैसे सुनिश्चित कर सकते हैं, कि आप अपने कैच ब्लॉक में घोषित भाग तक पहुँच गए हैं? क्या होगा अगर तात्कालिकता अपवाद को फेंकता है?


6
है ना? परिवर्तनीय घोषणाएं अपवाद नहीं फेंकती हैं।
जोशुआ

6
सहमत, यह तत्काल है कि अपवाद फेंक सकता है।
बर्कहार्ड

19

परंपरागत रूप से, सी-शैली भाषाओं में, घुंघराले ब्रेस के अंदर क्या होता है घुंघराले ब्रेस के अंदर रहता है। मुझे लगता है कि इस तरह के स्कोपों ​​में एक चर खिंचाव का जीवनकाल होने से अधिकांश प्रोग्रामर के लिए यह ठीक नहीं होगा। आप ब्रेसिज़ के दूसरे स्तर के अंदर की कोशिश / कैच / आखिर ब्लॉक को सम्मिलित करके आप जो चाहें प्राप्त कर सकते हैं। जैसे

... code ...
{
    string s = "test";
    try
    {
        // more code
    }
    catch(...)
    {
        Console.Out.WriteLine(s);
    }
}

संपादित करें: मैं हर नियम लगता है एक अपवाद है। निम्नलिखित सी ++ मान्य है:

int f() { return 0; }

void main() 
{
    int y = 0;

    if (int x = f())
    {
        cout << x;
    }
    else
    {
        cout << x;
    }
}

एक्स का स्कोप सशर्त, तत्कालीन क्लॉज और दूसरा क्लॉज है।


10

बाकी सभी ने मूल बातें उठाई हैं - एक ब्लॉक में क्या होता है एक ब्लॉक में रहता है। लेकिन .NET के मामले में, यह जांचने में मददगार हो सकता है कि कंपाइलर क्या सोच रहा है। उदाहरण के लिए, निम्नलिखित कोशिश / कैच कोड (ध्यान दें कि स्ट्रीमरेडर घोषित किया गया है, सही ढंग से, ब्लॉक के बाहर):

static void TryCatchFinally()
{
    StreamReader sr = null;
    try
    {
        sr = new StreamReader(path);
        Console.WriteLine(sr.ReadToEnd());
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    finally
    {
        if (sr != null)
        {
            sr.Close();
        }
    }
}

यह MSIL में निम्नलिखित के समान कुछ का संकलन करेगा:

.method private hidebysig static void  TryCatchFinallyDispose() cil managed
{
  // Code size       53 (0x35)    
  .maxstack  2    
  .locals init ([0] class [mscorlib]System.IO.StreamReader sr,    
           [1] class [mscorlib]System.Exception ex)    
  IL_0000:  ldnull    
  IL_0001:  stloc.0    
  .try    
  {    
    .try    
    {    
      IL_0002:  ldsfld     string UsingTest.Class1::path    
      IL_0007:  newobj     instance void [mscorlib]System.IO.StreamReader::.ctor(string)    
      IL_000c:  stloc.0    
      IL_000d:  ldloc.0    
      IL_000e:  callvirt   instance string [mscorlib]System.IO.TextReader::ReadToEnd()
      IL_0013:  call       void [mscorlib]System.Console::WriteLine(string)    
      IL_0018:  leave.s    IL_0028
    }  // end .try
    catch [mscorlib]System.Exception 
    {
      IL_001a:  stloc.1
      IL_001b:  ldloc.1    
      IL_001c:  callvirt   instance string [mscorlib]System.Exception::ToString()    
      IL_0021:  call       void [mscorlib]System.Console::WriteLine(string)    
      IL_0026:  leave.s    IL_0028    
    }  // end handler    
    IL_0028:  leave.s    IL_0034    
  }  // end .try    
  finally    
  {    
    IL_002a:  ldloc.0    
    IL_002b:  brfalse.s  IL_0033    
    IL_002d:  ldloc.0    
    IL_002e:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()    
    IL_0033:  endfinally    
  }  // end handler    
  IL_0034:  ret    
} // end of method Class1::TryCatchFinallyDispose

हम क्या देखते हैं? MSIL ब्लॉकों का सम्मान करता है - जब आप अपना C # संकलित करते हैं तो वे अंतर्निहित कोड का आंतरिक भाग होते हैं। गुंजाइश सी # कल्पना में मुश्किल-सेट नहीं है, यह सीएलआर और सीएलएस कल्पना में भी है।

गुंजाइश आपकी रक्षा करती है, लेकिन आप कभी-कभार इसके आसपास काम करते हैं। समय के साथ, आपको इसकी आदत हो जाती है, और यह स्वाभाविक लगने लगता है। जैसा कि बाकी सभी ने कहा, एक ब्लॉक में क्या होता है, उस ब्लॉक में रहता है। आप कुछ साझा करना चाहते हैं? आपको ब्लॉक के बाहर जाना होगा ...


8

किसी भी दर पर C ++ में, एक स्वचालित चर का दायरा घुंघराले ब्रेसिज़ द्वारा सीमित होता है जो इसे घेरता है। घुंघराले ब्रेस के बाहर एक कोशिश कीवर्ड नीचे रखकर किसी को यह अलग होने की उम्मीद क्यों होगी?


1
माना; "}" का अर्थ है एंड-ऑफ़-स्कोप। हालाँकि, कोशिश-कैच-अंततः इसमें असामान्य है कि एक कोशिश ब्लॉक के बाद, आपके पास एक पकड़ और / या अंत में ब्लॉक होना चाहिए ; इस प्रकार, सामान्य नियम का एक अपवाद जहां एक कोशिश ब्लॉक का दायरा संबद्ध कैच / अंत में स्वीकार्य है?
जॉन श्नाइडर

7

जैसा कि रैवेन्सपॉइंट ने बताया है, हर कोई उम्मीद करता है कि वेरिएबल उस ब्लॉक के लिए स्थानीय हो, जिसे वे परिभाषित करते हैं। tryएक ब्लॉक का परिचय देता है और ऐसा ही करता है catch

यदि आप दोनों के लिए स्थानीय चर चाहते हैं tryऔर catch, दोनों को एक खंड में संलग्न करने का प्रयास करें:

// here is some code
{
    string s;
    try
    {

        throw new Exception(":(")
    }
    catch (Exception e)
    {
        Debug.WriteLine(s);
    }
}

5

इसका सरल उत्तर यह है कि सी और इसके सिंटैक्स को विरासत में मिली अधिकांश भाषाएं ब्लॉक स्कोप हैं। इसका अर्थ है कि यदि एक खंड को {} के अंदर एक खंड में परिभाषित किया गया है, तो वह इसका कार्यक्षेत्र है।

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


4

@ बर्कहार्ड का सवाल है कि इसका ठीक से उत्तर क्यों दिया गया है, लेकिन एक नोट के रूप में मैं जोड़ना चाहता था, जबकि आपका अनुशंसित समाधान उदाहरण 99.9999 +% समय अच्छा है, यह अच्छा अभ्यास नहीं है, यह उपयोग करने से पहले या तो अशक्त के लिए जाँच करना अधिक सुरक्षित है। कोशिश ब्लॉक के भीतर कुछ पल, या चर को ब्लॉक करने के बजाय इसे घोषित करने से पहले किसी चीज को इनिशियलाइज़ करें। उदाहरण के लिए:

string s = String.Empty;
try
{
    //do work
}
catch
{
   //safely access s
   Console.WriteLine(s);
}

या:

string s;
try
{
    //do work
}
catch
{
   if (!String.IsNullOrEmpty(s))
   {
       //safely access s
       Console.WriteLine(s);
   }
}

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


4

MCTS सेल्फ-पेड ट्रेनिंग किट (परीक्षा 70-536) के पाठ 2 में "हाउ टू थ्रो एंड कैच एक्सेप्शन" शीर्षक के अनुसार : Microsoft® .NET फ्रेमवर्क 2.0- एप्लीकेशन डेवलपमेंट फाउंडेशन , इसका कारण यह है कि अपवाद हो सकता है। कोशिश ब्लॉक में चर घोषणाओं से पहले (जैसा कि दूसरों ने पहले ही नोट किया है)।

पृष्ठ 25 से उद्धरण:

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


4

जवाब, जैसा कि सभी ने बताया है, बहुत ज्यादा "यह है कि ब्लॉक कैसे परिभाषित किए जाते हैं"।

कोड को प्रीटियर करने के लिए कुछ प्रस्ताव हैं। एआरएम देखें

 try (FileReader in = makeReader(), FileWriter out = makeWriter()) {
       // code using in and out
 } catch(IOException e) {
       // ...
 }

क्लोजर के रूप में अच्छी तरह से यह माना जाता है।

with(FileReader in : makeReader()) with(FileWriter out : makeWriter()) {
    // code using in and out
}

अद्यतन: एआरएम जावा 7 में लागू किया गया है। http://download.java.net/jdk7/docs/technotes/guides/language/try-with-resources.html


2

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

यह बस अलग scopes के रूप में काम करना चाहिए।

try
    dim i as integer = 10 / 0 ''// Throw an exception
    dim s as string = "hi"
catch (e)
    console.writeln(s) ''// Would throw another exception, if this was allowed to compile
end try

2

चर ब्लॉक स्तर हैं और उस प्रयास या कैच ब्लॉक तक सीमित हैं। एक if स्टेटमेंट में एक वैरिएबल को परिभाषित करने के समान। इस स्थिति के बारे में सोचो।

try {    
    fileOpen("no real file Name");    
    String s = "GO TROJANS"; 
} catch (Exception) {   
    print(s); 
}

स्ट्रिंग को कभी घोषित नहीं किया जाएगा, इसलिए इसे निर्भर नहीं किया जा सकता है।


2

क्योंकि ट्रायल ब्लॉक और कैच ब्लॉक 2 अलग-अलग ब्लॉक हैं।

निम्नलिखित कोड में, क्या आप ब्लॉक बी में दिखाई देने वाले ब्लॉक ए में परिभाषित होंगे?

{ // block A
  string s = "dude";
}

{ // block B
  Console.Out.WriteLine(s); // or printf or whatever
}

2

हालांकि आपके उदाहरण में यह अजीब है कि यह काम नहीं करता है, इसे इसी तरह से लें:

    try
    {
         //Code 1
         String s = "1|2";
         //Code 2
    }
    catch
    {
         Console.WriteLine(s.Split('|')[1]);
    }

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

फिर से इस सिद्धांत को केवल अलग-अलग परिभाषाओं ( String s; s = "1|2";), या कुछ अन्य स्थितियों की अनुमति देकर तय किया जा सकता है , लेकिन आमतौर पर इसे केवल ना कहना आसान होता है।

इसके अतिरिक्त, यह गुंजाइश के शब्दार्थ को बिना किसी अपवाद के विश्व स्तर पर परिभाषित करने की अनुमति देता है, विशेष रूप से, स्थानीय लोगों को तब तक रहता है जब तक {}वे सभी मामलों में परिभाषित किए जाते हैं। मामूली बिंदु, लेकिन एक बिंदु।

अंत में, आप क्या चाहते हैं, इसे करने के लिए, आप ट्रैप कैच के चारों ओर कोष्ठक का एक सेट जोड़ सकते हैं। आपको वह गुंजाइश देता है जो आप चाहते हैं, हालांकि यह थोड़ा पठनीयता की कीमत पर आता है, लेकिन बहुत अधिक नहीं।

{
     String s;
     try
     {
          s = "test";
          //More code
     }
     catch
     {
          Console.WriteLine(s);
     }
}

1

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

लेकिन सामान्य तौर पर, शुरुआती अभिव्यक्तियाँ अपवादों को फेंक सकती हैं। यह उस चर के लिए कोई मतलब नहीं होगा जिसके शुरुआती ने एक अपवाद को फेंक दिया (या जो कि एक और चर के बाद घोषित किया गया था जहां ऐसा हुआ) पकड़ने के लिए गुंजाइश हो / अंत में।

इसके अलावा, कोड पठनीयता को नुकसान होगा। C (और C ++, Java और C # सहित) का अनुसरण करने वाली भाषाओं में नियम सरल है: वैरिएबल स्कोप ब्लॉक का अनुसरण करते हैं।

यदि आप चाहते हैं कि एक चर कोशिश / पकड़ / अंत में कहीं और हो, लेकिन पूरी चीज़ को ब्रेसिज़ (नंगे ब्लॉक) के दूसरे सेट में लपेटें और कोशिश से पहले चर घोषित करें।


1

जिस कारण से वे समान दायरे में नहीं हैं, इसका एक कारण यह है कि ट्रायल ब्लॉक के किसी भी बिंदु पर, आप अपवाद को फेंक सकते हैं। यदि वे एक ही दायरे में होते हैं, तो यह प्रतीक्षा में एक आपदा है, क्योंकि इस बात पर निर्भर करता है कि अपवाद कहां फेंका गया था, यह और भी अस्पष्ट हो सकता है।

कम से कम जब इसके प्रयास ब्लॉक के बाहर घोषित किया जाता है, तो आप यह सुनिश्चित करते हैं कि अपवाद को फेंकने पर न्यूनतम चर क्या हो सकता है; कोशिश ब्लॉक से पहले चर का मूल्य।


1

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

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


1

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


1

जैसा कि अन्य उपयोगकर्ताओं द्वारा बताया गया है, घुंघराले ब्रेसिज़ बहुत सी हर शैली की भाषा में गुंजाइश को परिभाषित करते हैं जो मुझे पता है।

यदि यह एक साधारण चर है, तो आप क्यों परवाह करते हैं कि यह कब तक दायरे में रहेगा? यह इतनी बड़ी बात नहीं है।

C # में, यदि यह एक जटिल वैरिएबल है, तो आप IDisposable को लागू करना चाहेंगे। फिर आप अंत में ब्लॉक में कोशिश / पकड़ / अंत में कॉल और obj.Dispose () का उपयोग कर सकते हैं। या आप कीवर्ड का उपयोग कर सकते हैं, जो कोड अनुभाग के अंत में डिस्पोज को स्वचालित रूप से कॉल करेगा।


1

पाइथन में वे कैच में दिखाई देते हैं / अंत में ब्लॉक करते हैं अगर लाइन उन्हें घोषित नहीं करती है।


1

क्या होगा अगर अपवाद कुछ कोड में फेंक दिया जाता है जो चर की घोषणा से ऊपर है। जिसका अर्थ है, घोषणा स्वयं इस मामले में खुश नहीं थी।

try {

       //doSomeWork // Exception is thrown in this line. 
       String s;
       //doRestOfTheWork

} catch (Exception) {
        //Use s;//Problem here
} finally {
        //Use s;//Problem here
}

1

सी # युक्ति (15.2) में कहा गया "एक स्थानीय चर या निरंतर के दायरे ब्लॉक IST एक ब्लॉक में घोषित कर दिया।"

(आपके पहले उदाहरण में कोशिश ब्लॉक वह ब्लॉक है जहां "s" घोषित किया गया है)


0

मेरा विचार यह होगा कि क्योंकि ट्रायल ब्लॉक में किसी चीज ने अपवाद को ट्रिगर कर दिया है, उसके नाम स्थान की सामग्री पर भरोसा नहीं किया जा सकता है - यानी पकड़ने के ब्लॉक में स्ट्रिंग 's' को संदर्भित करना अभी तक एक और अपवाद का कारण बन सकता है।


0

अगर यह एक संकलित त्रुटि नहीं है, और यदि आप इसे बाकी विधि के लिए घोषित कर सकते हैं, तो केवल प्रयास क्षेत्र में इसे घोषित करने का कोई तरीका नहीं होगा। यह आपको यह स्पष्ट करने के लिए मजबूर कर रहा है कि चर कहाँ मौजूद है और अनुमान नहीं लगाता है।


0

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

// won't compile!
try
{
    VeryLargeArray v = new VeryLargeArray(TOO_BIG_CONSTANT); // throws OutOfMemoryException
    string s = "Help";
}
catch
{
    Console.WriteLine(s); // whoops!
}

सीएलआर (और इसलिए संकलक) भी चर का उपयोग करने से पहले आपको वैरिएबल को शुरू करने के लिए मजबूर करते हैं। प्रस्तुत ब्लॉक में यह गारंटी नहीं दे सकता है।

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

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

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

उदाहरण के लिए आईडीसॉर्पोरेटिव ऑब्जेक्ट्स के साथ कीवर्ड का उपयोग करना :

using(Writer writer = new Writer())
{
    writer.Write("Hello");
}

के बराबर है:

Writer writer = new Writer();
try
{        
    writer.Write("Hello");
}
finally
{
    if( writer != null)
    {
        ((IDisposable)writer).Dispose();
    }
}

यदि आपकी कोशिश / पकड़ / अंत में समझने में मुश्किल है, तो इंटरमीडिएट कक्षा के साथ अप्रत्यक्ष की एक और परत को फिर से शुरू करने या शुरू करने का प्रयास करें जो कि आप जो हासिल करने की कोशिश कर रहे हैं उसके शब्दार्थों को एन्क्रिप्ट करते हैं। वास्तविक कोड देखे बिना, अधिक विशिष्ट होना कठिन है।


0

एक स्थानीय चर के बजाय, एक सार्वजनिक संपत्ति घोषित की जा सकती है; यह भी एक अप्रमाणित चर की एक और संभावित त्रुटि से बचना चाहिए। सार्वजनिक स्ट्रिंग S {प्राप्त करें; सेट; }


-1

यदि असाइनमेंट ऑपरेशन विफल हो जाता है तो आपका कैच स्टेटमेंट अशक्त चर में वापस संदर्भ होगा।


2
यह अप्रमाणित है। यह अशक्त (उदाहरण और स्थिर चर के विपरीत) भी नहीं है।
टॉम हैटिन -

-1

C # 3.0:

string html = new Func<string>(() =>
{
    string webpage;

    try
    {
        using(WebClient downloader = new WebClient())
        {
            webpage = downloader.DownloadString(url);
        }
    }
    catch(WebException)
    {
        Console.WriteLine("Download failed.");  
    }

    return webpage;
})();

WTF? क्यों डाउन वोट? एनकैप्सुलेशन OOP का अभिन्न अंग है। बहुत सुंदर लग रहा है।
कोर

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