रनटाइम में रेफ और आउट के बीच क्या अंतर है?


15

C # संदर्भ को पास करने के लिए तर्क देने के लिए refऔर outकीवर्ड प्रदान करता है । दोनों का शब्दार्थ बहुत समान है। एकमात्र अंतर fluted चर के आरंभ में है:

  • refफ़ंक्शन को पास करने से पहले वैरिएबल को इनिशियलाइज़ करना outपड़ता है , नहीं।
  • outचर को फ़ंक्शन के अंदर आरंभीकृत करने की आवश्यकता होती है, refनहीं।

इन दोनों खोजशब्दों के उपयोग के मामले भी लगभग समान हैं, और इनका बहुत अधिक बार उपयोग किया जाता है I एक कोड गंध माना जाता है (हालाँकि पैटर्न TryParseऔर TryGetValueपैटर्न जैसे मान्य उपयोग के मामले हैं )।

इस वजह से कोई समझा सकता है, इतने संकीर्ण उपयोग के मामलों के लिए C # में दो समान उपकरण क्यों हैं?

इसके अलावा, MSDN पर , यह कहा जाता है कि उनके पास अलग-अलग रन-टाइम व्यवहार है:

हालाँकि, रेफ और आउट कीवर्ड अलग-अलग रन-टाइम व्यवहार का कारण बनते हैं, लेकिन संकलन समय पर उन्हें विधि हस्ताक्षर का हिस्सा नहीं माना जाता है।

उनका रन-टाइम व्यवहार कैसे अलग है?

निष्कर्ष

दोनों उत्तर सही लगते हैं, आप दोनों को धन्यवाद। मैंने jmoreno को स्वीकार कर लिया है क्योंकि यह अधिक स्पष्ट है।


मेरा अनुमान है कि वे दोनों refC ++ की तरह ही कार्यान्वित हैं ; प्रश्न में वस्तु सूचक (या आदिम) को इंगित करता है। यानी Int32.TryParse(myStr, out myInt)(C #) उसी तरह "निष्पादित" int32_tryParse(myStr, &myInt)होता है जैसे (C) होगा; कीड़े को रोकने के लिए संकलक द्वारा लागू किए जाने वाले कुछ अवरोधों में एकमात्र अंतर। (मैं इसे एक उत्तर के रूप में पोस्ट करने वाला नहीं हूं क्योंकि मैं गलत हो सकता हूं कि यह पर्दे के पीछे कैसे काम करता है, लेकिन यह है कि मैं इसे कैसे काम करता हूं कल्पना करता हूं [क्योंकि यह समझ में आता है])
कोल जॉनसन

जवाबों:


10

जिस समय यह प्रश्न पूछा गया था, उस समय MSDN लेख बिल्कुल गलत था (इसे तब से ठीक कर लिया गया है )। "अलग व्यवहार का कारण" के बजाय यह "अलग व्यवहार की आवश्यकता है" होना चाहिए।

विशेष रूप से, कंपाइलर दो कीवर्ड के लिए अलग-अलग आवश्यकताओं को लागू करता है, भले ही व्यवहार को सक्षम करने के लिए एक ही mecanism (IL) का उपयोग किया जाता है।


इसलिए मेरी समझ यह है कि कंपाइलर किसी outपैरामीटर को निर्धारित करने या पैरामीटर असाइन न करने जैसी चीजों की जांच करता है ref, लेकिन यह जिस आईएल का उत्सर्जन करता है वह सिर्फ एक संदर्भ है। क्या वो सही है?
एंड्रयू

Btw, कोई इस तथ्य से यह बता सकता है कि out Tऔर ref Tअन्य CLI भाषाओं जैसे VB.Net या C ++ / CLI में पहचान की गई है।
ACH

@AndrewPiliser: सही। यह मानते हुए कि कोड किसी भी तरह से संकलित करता है (जब आपको ऐसा नहीं करना चाहिए तो आप इसे हटाने की कोशिश नहीं करते हैं), आईएल समान होगा।
jmoreno

4

इस विषय पर एक दिलचस्प राइटअप है जो आपके प्रश्न का उत्तर दे सकता है:

http://www.dotnetperls.com/ref

रूचि:

"रेफ और आउट के बीच का अंतर कॉमन लैंग्वेज रनटाइम में नहीं है, बल्कि C # भाषा में ही है।"

अपडेट करें:

मेरे काम के वरिष्ठ डेवलपर ने @ jororeno के उत्तर को ठीक किया, इसलिए सुनिश्चित करें कि आपने इसे पढ़ा है!


इसलिए अगर मैं सही ढंग से समझता हूं कि IL स्तर पर कोई अंतर नहीं है, जिसका अर्थ है कि उनके पास अलग-अलग समय व्यवहार नहीं हो सकता है। यह MSDN क्या कहता है के साथ विरोधाभास होगा। इंटरेस्टिन लेख फिर भी!
गॉबर एंगिएल

@ GáborAngyal क्या आपके पास MSDN लेख का एक लिंक होने की संभावना नहीं है? यह अच्छा हो सकता है कि यहाँ अगर राय अलग हो
Dan Beaulieu

यहाँ आप जाएँ: msdn.microsoft.com/en-gb/library/t3c3bfhx.aspx , लेकिन यह मेरे सवाल में था :)
Gábor Angyal

1
stringइस सब से क्या लेना देना है?
रॉबर्ट हार्वे

यह लेख से सिर्फ एक दृष्टांत है। दूसरी पंक्ति को हटाने के लिए अद्यतन किया गया ..
दान ब्यूलियू

2

रनटाइम ? बिलकुल नहीं। आप केवल रीफ या आउट कीवर्ड द्वारा भिन्न पैरामीटर के साथ एक विधि को अधिभारित नहीं कर सकते।

इसे संकलित करने का प्रयास करें और आपको एक संकलन त्रुटि मिलेगी "समान हस्ताक्षर वाला तरीका पहले से ही घोषित है":

    private class MyClass
    {
        private void DoSomething(out int param)
        {
        }
        private void DoSomething(ref int param)
        {
        }
    }

इस प्रश्न का उत्तर देने के लिए: "... इतने संकीर्ण उपयोग के मामलों के लिए C # में दो समान उपकरण क्यों हैं?"

एक कोड पठनीयता और एपीआई दृष्टिकोण से एक बड़ा अंतर है। एपीआई के एक उपभोक्ता के रूप में मुझे पता है कि जब "आउट" का उपयोग किया जाता है तो एपीआई आउट पैरामीटर पर निर्भर नहीं करता है। एपीआई डेवलपर के रूप में मैं "आउट" पसंद करता हूं और "रेफ" का उपयोग केवल तभी करता हूं जब (पूरी तरह से!) आवश्यक हो। एक महान चर्चा के लिए यह संदर्भ देखें:

/programming/1516876/when-to-use-ref-vs-out

सहायक जानकारी: मैंने निम्नलिखित विधि संकलित की और इसे अलग कर दिया। मैंने रेफरी और आउट कीवर्ड का उपयोग किया (इस उदाहरण में), लेकिन असेंबली कोड एक पते के संदर्भ के अलावा नहीं बदला, जैसा कि मुझे उम्मीद है:

    private class MyClass
    {
        internal void DoSomething(out int param)
        {
            param = 0;
        }
    }

00000000 धक्का ईबीपी
00000001 mov ईबीपी, esp
00000003 धक्का ईडीआई
00000004 धक्का ईएसआई
00000005 धक्का EBX
00000006 उप esp, 34h
00,000,009 XOR eax, eax
0000000b mov DWORD ptr [ईबीपी-10h], eax
0000000e mov DWORD ptr [ईबीपी-1Ch], EAX
00,000,011 Mov dword ptr [ebp-
3Ch ], ecx 00000014 mov dword ptr [ebp-40h], edx
00000017 cmp dword ptr ds: [008B1710h], 0
0000Beeeee2525
00000020 कॉल 6E6B601E
00000025 nop
param = 0;
00000026 mov eax, dword ptr [
ebp -40h] 00000029 xor edx, edx
0000002b mov dword ptr [eax], edx
}
0000002d nop
0000002e lea esp, [ebp-0Ch]
00000031 pop ebx
00000032 pop
esi 00000033 pop edi
00000034 pop
ebp 0000002

क्या मैं विधानसभा को सही ढंग से पढ़ रहा हूं?


आप जो लिखते हैं वह सही है, लेकिन कृपया ध्यान दें कि यह स्पष्ट संकेत नहीं है कि कोई रनटाइम अंतर नहीं है क्योंकि यह ओवरलोड की अनुमति नहीं है।
गॉबर एंगिएल

आह - अच्छी बात! क्या कोई ऊपर दिए गए कोड को अलग कर सकता है और मुझे सही या गलत साबित कर सकता है? मैं असेंबली पढ़ने में बहुत भयानक हूं, लेकिन जानने के लिए उत्सुक हूं।
श्मोकन

ठीक है - मैंने "आउट" और "रेफ" का उपयोग करते हुए कोड को
डिसाइड किया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.