2008-09-18 9 views
110

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

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

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

इस समस्या का सामान्य समाधान इसके बजाय प्रतीत होता है चर की घोषणा सिर्फ कोशिश ब्लॉक से पहले, के बजाय कोशिश ब्लॉक के भीतर:

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

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

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

उत्तर

139

दो बातें: वैश्विक और समारोह:

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

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

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

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

+2

हाय, आपकी व्याख्या पूरी तरह से सही है।हालांकि, कोशिश की गई कोशिश/पकड़ क्यों है? एक नेस्टेड कैच/आखिरकार ब्लॉक के साथ पकड़ने की कोशिश क्यों न करें, यानी {... पकड़ें {...} अंत में {...}}। (कंपाइलर को ब्लॉक की शुरुआत में परिवर्तनीय घोषणाओं को पकड़ने के लिए उन्हें पकड़ने के लिए ले जाना होगा। –

+2

एक संकलित भाषा (जैसे जावा या सी #) में, जब तक एक चरणीय दायरे में है, इससे कोई फर्क नहीं पड़ता कि यह कहां है घोषित किया गया - यह उस दायरे में कहीं और उपलब्ध है। – dkretz

+1

@ डिवो यदि आप जॉन के कोड को प्रस्तावित करते हैं तो भी आप बदलते हैं, फिर भी आप एक ही समस्या का सामना कर रहे हैं।;) {throw [...]; स्ट्रिंग एस = "ब्लाह"; पकड़ो {[...]} अंततः {लिखें (ओं)}}; – pek

52

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

+6

हू? परिवर्तनीय घोषणाएं अपवाद नहीं फेंकती हैं। – Joshua

+3

सहमत हैं, यह तत्काल है जो अपवाद फेंक सकता है। – Burkhard

0

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

0

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

8

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

+1

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

2

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

यह बस अलग-अलग क्षेत्रों के रूप में काम करना चाहिए।

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 
0

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

+1

यह असाइन नहीं किया गया है। यह भी शून्य नहीं है (उदाहरण और स्थिर चर के विपरीत)। –

2

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

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

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

1

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

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

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

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

17

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

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

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

int f() { return 0; } 

void main() 
{ 
    int y = 0; 

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

एक्स के दायरे सशर्त, तो खंड और बाकी खंड है।

4

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

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

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

कारण वे एक ही दायरे में नहीं हैं का एक हिस्सा है क्योंकि कोशिश ब्लॉक के किसी भी बिंदु पर है:

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

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

2

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

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

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

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

सरल जवाब है कि सी और भाषाओं कि अपने वाक्यविन्यास विरासत में मिली के सबसे कर रहे हैं ब्लॉक scoped है। इसका मतलब है कि यदि एक चर को एक ब्लॉक में परिभाषित किया गया है, यानी अंदर {}, यह उसका दायरा है।

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

1
While in your example it is weird that it does not work, take this similar one: 

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

This would cause the catch to throw a null reference exception if Code 1 broke. Now while the semantics of try/catch are pretty well understood, this would be an annoying corner case, since s is defined with an initial value, so it should in theory never be null, but under shared semantics, it would be. 

Again this could in theory be fixed by only allowing separated definitions (String s; s = "1|2";), or some other set of conditions, but it is generally easier to just say no. 

Additionally, it allows the semantics of scope to be defined globally without exception, specifically, locals last as long as the {} they are defined in, in all cases. Minor point, but a point. 

Finally, in order to do what you want, you can add a set of brackets around the try catch. Gives you the scope you want, although it does come at the cost of a little readability, but not too much. 

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

@burkhard क्यों उचित जवाब के रूप में सवाल है, लेकिन एक नोट के रूप में मैं जोड़ना चाहते थे, जबकि आपके सुझाए गए समाधान के उदाहरण अच्छा है समय की 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); 
    } 
} 

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

1

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

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

0

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

सादर,

1

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

1

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

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

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

3

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

कोड को सुंदर बनाने के कुछ प्रस्ताव हैं। देखें ARM

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

Closures रूप में अच्छी तरह इसे संबोधित करने वाले हैं।

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

अद्यतन: एआरएम http://download.java.net/jdk7/docs/technotes/guides/language/try-with-resources.html

8

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

.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 
:

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 में निम्न जैसा कुछ करने के लिए बाहर संकलन होगा

हम क्या देखते हैं? एमएसआईएल ब्लॉक का सम्मान करता है - जब आप अपना सी # संकलित करते हैं तो वे उत्पन्न अंतर्निहित कोड का आंतरिक रूप से हिस्सा होते हैं। दायरा सी # स्पेक में बस कड़ी मेहनत नहीं है, यह सीएलआर और सीएलएस स्पेक में भी है।

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

+0

+1? डाउन वोट क्यों? Encapsulation ओओपी के अभिन्न अंग है। बहुत सुंदर लग रहा है। –

0

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

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

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

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

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

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

उदा। में IDisposable वस्तुओं के साथ का उपयोग कर कीवर्ड:

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

के बराबर है:

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

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

0

सी # 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; 
})(); 
+0

डब्ल्यूटीएफ के लिए – core

+0

सहमत हैं, इसमें क्या गलत है? मैं जानना चाहता हूं! –

+1

मैं डाउनवोट नहीं था, लेकिन गलत क्या है एक अनियमित स्ट्रिंग लौट रहा है। –

1

अजगर में वे पकड़/अंत में ब्लॉक में दिखाई दे रहे हैं, तो लाइन उन्हें घोषित फेंक नहीं किया।

3

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

पेज 25 से उद्धरण:।

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

1

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

try { 

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

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

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