2010-02-25 9 views
32

मैं मैं ऐसा करते हैं तो एक System.StackOverflowException:क्यों सी # कंपाइलर खुद को संदर्भित करने से गुण बंद नहीं करता है?

private string abc = ""; 
public string Abc 
{ 
    get 
    { 
     return Abc; // Note the mistaken capitalization 
    } 
} 

मुझे समझ में क्यों - संपत्ति ही संदर्भित कर रहा है, अनंत लूप के लिए अग्रणी। (पिछले प्रश्न देखें here और here)।

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

+2

"खुद को संदर्भित करके", मुझे लगता है कि मैं वास्तव में "खुद को बुलावा" कहने का मतलब हूं, लेकिन आपको यह विचार मिलता है। –

उत्तर

42

आप अंतिम टिप्पणी here पर "आधिकारिक" कारण देख सकते हैं।

दृश्य स्टूडियो के लिए सुझाव के लिए पर 14/11/2008 पर माइक्रोसॉफ्ट द्वारा प्रकाशित किया गया था 19:52

धन्यवाद!

आप सही है कि हम आसानी से संपत्ति प्रत्यावर्तन का पता लगा सकता है, लेकिन हम गारंटी नहीं दे सकते कुछ भी नहीं उपयोगी प्रत्यावर्तन के द्वारा पूरा किया जा रहा है कि वहाँ। संपत्ति के शरीर अपने वस्तु जो अगले प्रत्यावर्तन का व्यवहार बदलने पर अन्य क्षेत्रों सेट कर सकते हैं, अपने व्यवहार कंसोल, से उपयोगकर्ता इनपुट के आधार पर बदल सकता है या यहाँ तक कि यादृच्छिक मूल्यों पर अलग तरह से आधारित व्यवहार कर सकता है। इन मामलों में, स्वयं-पुनरावर्ती संपत्ति वास्तव में रिकर्सन को समाप्त कर सकती है, लेकिन हमारे पास यह निर्धारित करने का कोई तरीका नहीं है कि यह संकलन समय पर है (बिना समस्या को हल किए बिना!)।

(यह ले जाते थे और परिवर्तन तोड़ने इस नामंज़ूर) उपरोक्त कारणों से, हम करने में सक्षम नहीं होगा के लिए निषेध आत्म पुनरावर्ती गुण।

एलेक्स टर्नर

कार्यक्रम प्रबंधक

विजुअल C# कंपाइलर

+20

यह अच्छा हो सकता है अगर उन्होंने इसके बारे में एक कंपाइलर चेतावनी उत्पन्न की। मुझे लगता है कि यह मूल्यवान होगा। – Nick

+0

+1 "आधिकारिक" स्रोत से अच्छा पूरा जवाब। – auujay

+0

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

1

शायद उन्हें लगता है कि यह बिना किसी वास्तविक लाभ के संकलक को अनावश्यक जटिल करेगा।

आप पहली बार इस संपत्ति को कॉल करते समय आसानी से इस टाइपो को खोज लेंगे।

0

अन्य मामलों मामलों है कि यह जाँच करता है के लिए (पुनरावर्ती निर्माता को छोड़कर) अमान्य हैं आईएल।
इसके अतिरिक्त, उन सभी मामलों, यहां तक ​​कि पुनरावर्ती रचनाकार) विफल होने के लिए गारेन किए गए हैं।

हालांकि, संभवतः एक उपयोगी रिकर्सिव संपत्ति (if कथन का उपयोग करके) संभवतः यद्यपि संभव है।

9

संपत्ति का जिक्र करते हुए संपत्ति हमेशा अनंत रिकर्सन और स्टैक ओवरफ़्लो का कारण नहीं बनती है। उदाहरण के लिए, इस ठीक काम करता है:

int count = 0; 
public string Abc 
{ 
    count++; 
    if (count < 1) return Abc; 
    return "Foo"; 
} 

ऊपर एक डमी उदाहरण है, लेकिन मुझे यकीन है कि एक उपयोगी पुनरावर्ती कोड है कि इसी तरह की है के साथ आ सकता है कर रहा हूँ। कंपाइलर यह निर्धारित नहीं कर सकता कि अनंत रिकर्सन होगा (समस्या को रोकना)।

साधारण मामले में चेतावनी उत्पन्न करना सहायक होगा।

1

सबसे पहले, आपको अप्रयुक्त चर abc के लिए चेतावनी मिलेगी।

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

11

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

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

इसके विपरीत, हम एक चेतावनी दे अगर आप कुछ इस तरह करते हैं :

int customerId; 
... 
this.customerId= this.customerId; 

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

+0

मैं एलेक्स के जवाब पर टिप्पणियों पर चर्चा कर रहा था। आपका बयान है कि "लेकिन चूंकि यह गैरकानूनी कोड है, इसलिए संभवतः आप ऐसा करने का मतलब नहीं रखते थे। चूंकि यह बहुत ही मरने वाला नहीं है, इसलिए हम एक चेतावनी देते हैं कि यहां कुछ ऐसा है जिसका आप शायद इरादा नहीं रखते" आपके ब्लॉग का विरोधाभास है यहां पोस्ट करना: http://blogs.msdn.com/ericlippert/archive/2010/01/25/why-are-unused-using-directives-not-a-warning.aspx – Nick

+1

@ निक: मैं नहीं देख रहा हूँ अंतर्विरोध। (इसका मतलब यह नहीं है कि कोई नहीं है: मैं बड़ा हूं, इसमें बहुत से लोग हैं।) मैं सिर्फ यह नहीं देख रहा हूं कि आप क्या प्राप्त कर रहे हैं। –

+0

@ एरिक लिपर्ट: गीत के स्वयं के संदर्भ के लिए धन्यवाद। :-) – jason

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