2008-09-17 17 views
10

सी # में आप किसी विधि के अंदर एक ब्लॉक बना सकते हैं जो किसी अन्य कथन से जुड़ा नहीं है।सी # में एक अज्ञात unattached ब्लॉक का मूल्य क्या है?

public void TestMethod() 
    { 
     { 
      string x = "test"; 
      string y = x; 

      { 
       int z = 42; 
       int zz = z; 
      } 
     } 
    } 

यह कोड संकलित करता है और चलाता है जैसे कि मुख्य विधि के अंदर ब्रेसिज़ नहीं थे। ब्लॉक के अंदर ब्लॉक भी ध्यान दें।

क्या कोई परिदृश्य है जहां यह मूल्यवान होगा? मुझे अभी तक कोई नहीं मिला है, लेकिन अन्य लोगों के निष्कर्षों को सुनने के लिए उत्सुक हूं।

उत्तर

11

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

Ray Hayes बताते हैं कि .NET कचरा कलेक्टर तुरंत आउट-ऑफ-स्कोप ऑब्जेक्ट्स एकत्र नहीं करेगा, इसलिए स्कोपिंग मुख्य लाभ है।

+1

क्या आपने वास्तव में इसे वीएम स्तर पर सत्यापित किया है? अधिकांश उचित कंपाइलर और जीसी संकलन प्रक्रिया के दौरान दो ब्लॉक को एक में पतन कर देंगे, और जीसी वैरिएबल के अंतिम उपयोग के बाद एक मान कर सकते हैं जो इसे संदर्भित करता है। – emk

+0

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

+2

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

1

जहाँ तक मैं देख सकता हूं, यह केवल संगठनात्मक दृष्टिकोण से उपयोगी होगा। मैं वास्तव में ऐसा करने में किसी भी तार्किक मूल्य की कल्पना नहीं कर सकता। शायद किसी के पास एक उचित उदाहरण होगा।

0

ऐसा करने का एक कारण यह है कि वेरिएबल्स 'z' और 'zz' उस आंतरिक ब्लॉक के अंत के नीचे कोड पर उपलब्ध नहीं होंगे। जब आप जावा में ऐसा करते हैं, तो JVM आंतरिक कोड के लिए एक स्टैक फ्रेम को धक्का देता है, और वे मान स्टैक पर रह सकते हैं। जब कोड ब्लॉक से बाहर निकलता है, तो स्टैक फ्रेम पॉप हो जाता है और वे मान दूर जाते हैं। शामिल प्रकारों के आधार पर, यह आपको ढेर और/या कचरा संग्रह का उपयोग करने से बचा सकता है।

3

यह एक पार्सर नियम का उप-उत्पाद है कि कथन या तो एक सरल कथन या ब्लॉक है। यानी जहां भी एक कथन कर सकते हैं वहां एक ब्लॉक का उपयोग किया जा सकता है।

उदा।

if (someCondition) 
SimpleStatement(); 

if (SomeCondition) 
{ 
    BlockOfStatements(); 
} 

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

तो आम तौर पर यह मूल्यवान नहीं है।

0

सी # - जैसे सी/सी ++/जावा - ब्रेसिज़ एक दायरे को दर्शाते हैं। यह एक चर के जीवनकाल को निर्देशित करता है। चूंकि बंद ब्रेस तक पहुंच जाता है, तो चर एक कचरा संग्रह के लिए तत्काल उपलब्ध हो जाता है। सी ++ में, अगर वर्ग एक उदाहरण का प्रतिनिधित्व करता है तो यह वर्ग के विनाशक को बुलाया जाएगा।

उपयोग के लिए, एकमात्र संभव उपयोग एक बड़ी वस्तु को मुक्त करना है, लेकिन टीबीएच, इसे शून्य पर सेट करना एक ही प्रभाव होगा। मुझे संदेह है कि पूर्व उपयोग शायद सी ++ प्रोग्रामर को कुछ हद तक परिचित और आरामदायक क्षेत्र में प्रबंधित कोड में ले जाने के लिए है। यदि वास्तव में सी # में "विनाशक" को कॉल करना चाहते हैं, तो आप आम तौर पर IDISposable इंटरफ़ेस को लागू करते हैं और "उपयोग (var) {...}" पैटर्न का उपयोग करते हैं।

Oisin

0

यहां तक ​​कि अगर यह वास्तव में किसी भी कारण से (जैसे चर गुंजाइश नियंत्रण) के लिए उपयोगी था, मैं तुम्हें अच्छे पुराने कोड readibility के दृष्टिकोण से इस तरह के निर्माण से हतोत्साहित होगा।

0

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

public void TestMethod() 
{ 
    //do something with some strings 
    string x = "test"; 
    string y = x; 

    //do something else with some ints 
    int z = 42; 
    int zz = z; 
} 
4

यदि आप एक चर नाम का पुन: उपयोग करना चाहता था एक उदाहरण हो सकता है, सामान्य रूप से आप पुन: उपयोग नहीं कर सकते चर नाम यह वैध

 int a = 10; 
     Console.WriteLine(a); 

     int a = 20; 
     Console.WriteLine(a); 

नहीं है, बल्कि यह है:

{ 
     int a = 10; 
     Console.WriteLine(a); 
    } 
    { 
     int a = 20; 
     Console.WriteLine(a); 
    } 

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

{ 
     //Process a large object and extract some data 
    } 
    //large object is out of scope here and will be garbage collected, 
    //you can now perform other operations with the extracted data that can take a long time, 
    //without holding the large object in memory 

    //do processing with extracted data 
1

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

switch(value) 
{ 
    case const1: 
     int i = GetValueSomeHow(); 
     //do something 
     return i.ToString(); 

    case const2: 
     int i = GetADifferentValue(); 
     //this will throw an exception - i is already declared 
... 

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

switch(value) 
{ 
    case const1: 
    { 
     int i = GetValueSomeHow(); 
     //do something 
     return i.ToString(); 
    } 

    case const2: 
    { 
     int i = GetADifferentValue(); 
     //no exception now 
     return SomeFunctionOfInt(i); 
    } 
... 

यह गेटोस और लेबल के लिए भी काम कर सकता है, न कि आप अक्सर उन्हें सी # में उपयोग करते हैं।

1

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

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

एरिक लिपर्ट से this recent blog post की शुरुआत पर विचार करें। एक if कथन का पालन किसी भी कथन या घुंघराले ब्रेसिज़ पर संलग्न कई बयान के बाद नहीं होता है, यह केवल एक ही कथन के बाद होता है। जब भी आप घुंघराले ब्रेसिज़ में 0 से एन कथन संलग्न करते हैं तो आप कोड के बराबर (भाषा पार्सर के दृष्टिकोण से) एक कथन बनाते हैं। यह वही अभ्यास सभी लूपिंग संरचनाओं पर भी लागू होता है, हालांकि ब्लॉग पोस्ट के मुख्य बिंदु के अनुसार, यह कोशिश/पकड़/आखिरकार ब्लॉक पर लागू नहीं होता है।

उस बिंदु से ब्लॉक को संबोधित करते समय प्रश्न बन जाता है, "क्या ब्लॉक को किसी भी कथन का उपयोग करने से रोकने के लिए एक अनिवार्य कारण है?" और जवाब नहीं है"।

संबंधित मुद्दे