जैसा कि अन्य ने ध्यान दिया है, आपके पास "ref to variable" प्रकार का क्षेत्र नहीं हो सकता है। हालांकि, सिर्फ यह जानकर कि आप ऐसा नहीं कर सकते हैं शायद असंतुष्ट है; आप शायद पहले भी जानना चाहते हैं, क्यों नहीं, और दूसरा, इस प्रतिबंध को कैसे प्राप्त करें।
कारण है कि केवल तीन संभावनाएं देखते हैं क्योंकि:
1) रेफरी प्रकार के क्षेत्रों
2) रेफरी प्रकार के असुरक्षित क्षेत्रों
3) अस्थायी भंडारण का उपयोग न करें की अनुमति दें को अनुमति न दें स्थानीय चर के लिए पूल (उर्फ "स्टैक")
मान लीजिए कि हमने रेफ प्रकार के फ़ील्ड की अनुमति दी है। तो फिर तुम
public ref int x;
void M()
{
int y = 123;
this.x = ref y;
}
कर सकता है और अब y M
पूर्ण होने के बाद पहुँचा जा सकता है। इसका मतलब है कि या तो हम मामले में हैं (2) - this.x
तक पहुंचने से दुर्घटनाग्रस्त हो जाएगा और मर जाएगा क्योंकि वाई के लिए भंडारण अब मौजूद नहीं है - या हम मामले में हैं (3), और स्थानीय y
कचरे पर संग्रहीत है एकत्रित ढेर, अस्थायी स्मृति पूल नहीं।
हमें अनुकूलन पसंद है कि स्थानीय चर को अस्थायी पूल पर संग्रहीत किया जाए, भले ही वे रेफरी से गुजर रहे हों, और हम इस विचार से नफरत करते हैं कि आप एक समय बम छोड़ सकते हैं जो आपके प्रोग्राम को दुर्घटनाग्रस्त कर सकता है और बाद में मर सकता है। इसलिए, विकल्प एक यह है: कोई रेफ फ़ील्ड नहीं।
ध्यान दें कि अज्ञात कार्यों के बंद-ओवर चर के स्थानीय चर के लिए हम विकल्प (3) चुनते हैं; उन स्थानीय चर को अस्थायी पूल से आवंटित नहीं किया जाता है।
जो हमें दूसरे प्रश्न पर लाता है: आप इसके आसपास कैसे जाते हैं? कारण है कि आप एक रेफरी क्षेत्र चाहते हैं एक गेटर और अन्य चर के सेटर बनाने के लिए है, तो यह है कि पूरी तरह से कानूनी है:
sealed class Ref<T>
{
private readonly Func<T> getter;
private readonly Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
...
Ref<int> x;
void M()
{
int y = 123;
x = new Ref<int>(()=>y, z=>{y=z;});
x.Value = 456;
Console.WriteLine(y); // 456 -- setting x.Value changes y.
}
और वहाँ तुम जाओ। y
जीसी ढेर पर संग्रहीत है, और x
एक ऐसी वस्तु है जिसमें y
प्राप्त करने और सेट करने की क्षमता है।
ध्यान दें कि सीएलआर रेफ स्थानीय लोगों और रिफ्रेंसिंग विधियों का समर्थन करता है, हालांकि सी # नहीं है। शायद सी # का एक काल्पनिक भविष्य संस्करण इन सुविधाओं का समर्थन करेगा; मैंने इसे प्रोटोटाइप किया है और यह अच्छी तरह से काम करता है। हालांकि, यह प्राथमिकता सूची पर वास्तविक नहीं है, इसलिए मुझे अपनी आशाएं नहीं मिलेंगी।
अद्यतन: ऊपर दिए गए अनुच्छेद में उल्लिखित सुविधा अंततः सी # 7 में वास्तविक के लिए लागू की गई थी। हालांकि, आप अभी भी एक क्षेत्र में एक रेफरी स्टोर नहीं कर सकते हैं।
क्या आप दूसरे पैराग्राफ को थोड़ा सा विस्तारित करना चाहते हैं? "एक बड़ा म्यूटेबल ऑब्जेक्ट" मेरे लिए पूरी तरह से स्पष्ट नहीं है। साथ ही, स्ट्रिंगवॉपर कैसे काम करेगा यदि किसी क्षेत्र में स्ट्रिंग संदर्भ को पकड़ने का कोई तरीका नहीं है? –
मैंने एक उदाहरण दिया है जिसे स्पष्ट करना चाहिए। जैसा कि मैंने कहा, एक असली डिजाइन में स्ट्रिंगवॉपर शायद एक स्ट्रिंग से अधिक होल्डिंग ऑब्जेक्ट होगा। –
विचार के लिए धन्यवाद। मेरा उदाहरण शायद सरलीकृत हो गया था क्योंकि मेरे वास्तविक कोड में वास्तव में एक ऑब्जेक्ट (स्ट्रिंग नहीं) है जिसे मैं संदर्भ द्वारा असाइन करने का प्रयास कर रहा हूं। जिस व्यवहार को मैं ढूंढ रहा हूं वह किसी ऑब्जेक्ट के किसी उपयोगकर्ता को ऑब्जेक्ट को शून्य करने में सक्षम होने की अनुमति देना है, या उस प्रकार के नए उदाहरण को इसके तरीकों से भी असाइन करना है। मैं ऑब्जेक्ट को कुछ निर्भरता इंजेक्शन के हिस्से के रूप में कन्स्ट्रक्टर के माध्यम से पास करता हूं और इसलिए अन्य विधियां केवल फ़ील्ड तक पहुंचकर वस्तु को देख सकती हैं। ऐसा लगता है कि मैं जो हासिल करना चाहता हूं वह शर्म की बात नहीं है। – Jamie