2015-01-07 7 views
19

मैं निम्नलिखित कोड है कहते हैं:क्या इंट रेफ पैरामीटर बॉक्सिंग मिलता है?

void Main() 
{ 
    int a = 5; 
    f1(ref a); 
} 

public void f1(ref int a) 
{ 
    if(a > 7) return; 
    a++; 
    f1(ref a); 
    Console.WriteLine(a); 
} 

आउटपुट है:

8 8 8 

अर्थात जब ढेर रेफरी पैरामीटर का मान unwinds बनाए रखा है।

क्या इसका मतलब यह है कि ref keyword से int parameter को बॉक्सिंग करने का कारण बनता है?
रिकर्सिव कॉल के दौरान वास्तविक स्टैक कैसा दिखता है?

+11

संभवतः मेरी ज्ञान की कमी, लेकिन चलो चलते हैं: रेफरी द्वारा एक मूल्य प्रकार को पार करने से मूल्य की बजाय पारित होने के लिए स्टैक पर स्थिति होती है। मुक्केबाजी और अनबॉक्सिंग के साथ इसका कोई लेना-देना नहीं है, सही? – Adimeus

+5

एमएसडीएन से: "संदर्भ द्वारा पारित होने पर मूल्य प्रकार का कोई मुक्केबाजी नहीं है।" –

उत्तर

24

संदर्भ द्वारा एक मान प्रकार पासिंग ढेर पर इसके स्थिति का कारण बनता है मूल्य ही बजाय पारित कर दिया करने के लिए। इसका मुक्केबाजी और अनबॉक्सिंग से कोई लेना देना नहीं है। यह इस बारे में सोचता है कि रिक्त कॉल के दौरान स्टैक कैसा दिखता है, क्योंकि प्रत्येक एकल कॉल स्टैक पर "समान" स्थान को संदर्भित करता है।

मुझे लगता है कि भ्रम का एक बहुत MSDN's paragraph on boxing and unboxing से आता है:

मुक्केबाजी प्रक्रिया है जिसके तहत एक मान प्रकार एक संदर्भ प्रकार में बदल जाता है करने के लिए व्यक्ति का नाम है। जब आप एक चर को बॉक्स करते हैं, तो आप एक संदर्भ चर बना रहे हैं जो ढेर पर एक नई प्रति को इंगित करता है। संदर्भ चर, एक वस्तु है ...

संभवत: दो अलग बातें के बीच आप भ्रमित: 1) एक वस्तु है, जो कर रहा है कहने के लिए एक मान प्रकार के रूप में आप करेंगे "परिवर्तित", परिभाषा एक संदर्भ प्रकार:

int a = 5; 
object b = a; // boxed into a reference type 

और 2) एक मूल्य के प्रकार पैरामीटर के गुजरने के साथ संदर्भ द्वारा:

main(){ 
    int a = 5; 
    doWork(ref a); 
} 
void doWork(ref int a) 
{ 
    a++; 
} 

जो दो अलग-अलग चीजें हैं।

+3

शायद सबसे अच्छा स्पष्टीकरण ... ध्यान दें कि "स्टैक पर" प्रश्न में उल्लिखित विशिष्ट मामला है, मूल्य प्रकार को स्टैक पर आवंटित नहीं किया जाना चाहिए। हो सकता है कि "पूर्ण स्थिति (यानी ढेर पर)" अधिक सामान्य हो - यह सुनिश्चित न करें कि यह सी/सी ++ पृष्ठभूमि के बिना लोगों के लिए कैसे पढ़ता है। –

2

मुझे लगता है कि आप int पैरामीटर बॉक्सिंग किए जा रहे हैं में गलत हैं। MSDN से,

मुक्केबाजी किसी भी अंतरफलक यह मान प्रकार

द्वारा कार्यान्वित प्रकार के प्रकार वस्तु या को एक मान प्रकार परिवर्तित करने की प्रक्रिया क्या तुम यहाँ है एक int पैरामीटर द्वारा पारित किया जा रहा है संदर्भ, विशेष रूप से यह एक "मूल्य प्रकार" संदर्भ द्वारा पारित किया जा रहा है।

आप विवरण के लिए पास पैरामीटर पर जॉन स्कीट के उत्कृष्ट explanation का उल्लेख कर सकते हैं।

+0

हां, लेकिन रनटाइम के लिए 'f1' का पैरामीटर प्रकार' System.Int32' नहीं है, यह तथाकथित रेफ प्रकार 'System.Int32 &' है, जो खुद को मान प्रकार के रूप में रिपोर्ट नहीं करता है। –

8

यह एक कार्यक्रम अलग परिणाम है कि क्या ref int बॉक्सिंग हो जाता है पर निर्भर करता है दे सकता है कि बनाने के लिए आसान है:

static void Main() 
{ 
    int a = 5; 
    f(ref a, ref a); 
} 

static void f(ref int a, ref int b) 
{ 
    a = 3; 
    Console.WriteLine(b); 
} 

आप क्या मिलता है? मैं मुद्रित देखता हूं।

बॉक्सिंग में प्रतियां बनाना शामिल है, इसलिए ref a बॉक्स किए गए थे, तो आउटपुट 5 होगा। इसके बजाय, a और b दोनों Main में मूल a चर के संदर्भ हैं। यदि यह मदद करता है, तो आप ज्यादातर (पूरी तरह से नहीं) पॉइंटर्स के रूप में उनके बारे में सोच सकते हैं।

3

आपके Console.WriteLine(a); रिकर्सन समाप्त होने के बाद निष्पादित किया जाएगा। घुसपैठ समाप्त हो जाती है जब int का मूल्य 8 हो जाता है। और इसे 8 तक बनाने के लिए इसे 3 बार रिकर्सन किया जाता है। तो, पिछले के बाद यह 8 प्रिंट होगा और उसके बाद प्रत्यावर्तन जो ऊपर 8 फिर से संदर्भित किया जाता चर महत्व है के रूप में प्रिंट होगा को नियंत्रण बढ़ाने के बन 8.

इसके अलावा ILDASM उत्पादन

.method public hidebysig static void f1(int32& a) cil managed 
{ 
    // Code size  26 (0x1a) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: ldind.i4 
    IL_0002: ldc.i4.7 
    IL_0003: ble.s  IL_0006 
    IL_0005: ret 
    IL_0006: ldarg.0 
    **IL_0007: dup** 
    IL_0008: ldind.i4 
    IL_0009: ldc.i4.1 
    IL_000a: add 
    IL_000b: stind.i4 
    IL_000c: ldarg.0 
    IL_000d: call  void ConsoleApplication1.Program::f1(int32&) 
    IL_0012: ldarg.0 
    IL_0013: ldind.i4 
    IL_0014: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_0019: ret 
} // end of method Program::f1 
+1

यह सब सही है, लेकिन यह किसी भी पवन के सवालों का जवाब नहीं देता है। :) – gehho

+0

जहाँ तक मुझे पता है कि मुक्केबाजी नहीं हो रही है। यह सिर्फ ढेर पर नवीनतम मूल्य धक्का दे रहा है। – Amit

2

जाँच यह एक बॉक्सिंग नहीं है।

वहाँ MSDN ref keyword documentation में स्पष्ट विवरण:

संदर्भ प्रकार की अवधारणा के साथ संदर्भ द्वारा पारित करने की अवधारणा को भ्रमित न हों। दो अवधारणाएं समान नहीं हैं। एक विधि पैरामीटर को बिना किसी मान प्रकार या संदर्भ प्रकार के भले ही संशोधित किया जा सकता है। जब संदर्भ द्वारा पारित किया जाता है तो मूल्य प्रकार का कोई मुक्केबाजी नहीं होता है।

2

मौजूदा जवाब यह कैसे लागू किया गया है करने के लिए जोड़ा जा रहा है:

CLR इसलिए कामयाब संकेत कहा जाता है समर्थन करता है। ref ढेर पर चर के लिए एक प्रबंधित सूचक पास करता है। आप ढेर स्थानों को भी पास कर सकते हैं:

var array = new int[1]; 
F(ref array[0]); 

आप फ़ील्ड के संदर्भ भी पारित कर सकते हैं।

इसका परिणाम पिनिंग में नहीं होता है। प्रबंधित पॉइंटर्स रनटाइम (विशेष रूप से जीसी द्वारा) द्वारा समझा जाता है। वे स्थानापन्न हैं। वे सुरक्षित और सत्यापन योग्य हैं।

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