2012-04-25 21 views
10

ये एक सी # पुस्तक से उदाहरण हैं जो मुझे लगता है कि यह उदाहरण वास्तव में क्या कर रहा है, यह समझने में थोड़ी परेशानी हो रही है कि मुझे यह समझने में मदद करने के लिए एक स्पष्टीकरण चाहिए कि यहां क्या हो रहा है।मूल्य और संदर्भ द्वारा संदर्भ

 //creates and initialzes firstArray 
     int[] firstArray = { 1, 2, 3 }; 

     //Copy the reference in variable firstArray and assign it to firstarraycopy 
     int[] firstArrayCopy = firstArray; 

     Console.WriteLine("Test passing firstArray reference by value"); 


     Console.Write("\nContents of firstArray " + 
      "Before calling FirstDouble:\n\t"); 

     //display contents of firstArray with forloop using counter 
     for (int i = 0; i < firstArray.Length; i++) 
      Console.Write("{0} ", firstArray[i]); 

     //pass variable firstArray by value to FirstDouble 
     FirstDouble(firstArray); 

     Console.Write("\n\nContents of firstArray after " + 
      "calling FirstDouble\n\t"); 

     //display contents of firstArray 
     for (int i = 0; i < firstArray.Length; i++) 
      Console.Write("{0} ", firstArray[i]); 

     // test whether reference was changed by FirstDouble 
     if (firstArray == firstArrayCopy) 
      Console.WriteLine(
       "\n\nThe references refer to the same array"); 
     else 
      Console.WriteLine(
       "\n\nThe references refer to different arrays"); 

     //method firstdouble with a parameter array 
     public static void FirstDouble(int[] array) 
    { 
     //double each elements value 
     for (int i = 0; i < array.Length; i++) 
      array[i] *= 2; 

     //create new object and assign its reference to array 
     array = new int[] { 11, 12, 13 }; 

मूल रूप से वहाँ कोड मैं जानना चाहूंगा कि क्या उस किताब सरणी मूल फोन करने वाले की तुलना में मूल्य से पारित हो जाता है, तो विधि (मैं क्या समझ से) द्वारा संशोधित नहीं प्राप्त करता है कह रहा है है। तो विधि के अंत की ओर पहली बार वे स्थानीय वैरिएबल सरणी को तत्वों के एक नए सेट में विफल और असाइन करते हैं जो विफल हो जाते हैं और प्रदर्शित होने पर मूल कॉलर के नए मान 2,4,6 होते हैं।

अब मेरा भ्रम यह है कि विधि में लूप के लिए कैसे किया गया है पहले दोहरी मूल कॉलर को संशोधित करें, अगर यह मान द्वारा पारित किया गया तो 2,4,6 पर निकालें। मैंने सोचा कि मूल्य 1,2,3 रहना चाहिए।

अग्रिम

धन्यवाद
+0

[वैल्यू टाइप और संदर्भ प्रकार की समस्या] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/6070892/value-type-and-reference-type-problem) –

+0

@AlexeiLevenkov इस के साथ कहीं और अच्छी तरह से कवर किया गया है, मैं 'उस के लिए बंद करने से नफरत है :( –

उत्तर

30

इस समझ के लिए महत्वपूर्ण एक value type and a reference type के बीच अंतर पता करने के लिए है।

उदाहरण के लिए, एक सामान्य मान प्रकार, int पर विचार करें।

int a = 1; 
int b = a; 
a++; 

के बाद इस कोड को निष्पादित किया गया है, a मान 2 है, और b मूल्य 1 है। क्योंकि int एक मान प्रकार है, b = aa के मान की एक प्रति लेता है।

अब एक वर्ग पर विचार करें:

MyClass a = new MyClass(); 
a.MyProperty = 1; 
MyClass b = a; 
a.MyProperty = 2; 

क्योंकि कक्षाएं संदर्भ प्रकार के होते हैं, b = a केवल संदर्भ के बजाय मूल्य की तुलना में प्रदान करती है। तो b और a दोनों एक ही वस्तु का संदर्भ लें। इसलिए, a.MyProperty = 2 निष्पादित करने के बाद, b.MyProperty == 2a और b उसी वस्तु का संदर्भ लें।

public static void FirstDouble(int[] array) 

चर array वास्तव में, एक संदर्भ है क्योंकि int[] एक संदर्भ प्रकार है:


अपने प्रश्न में कोड को देखते हुए, एक सरणी के लिए एक संदर्भ के प्रकार और इसलिए इस कार्य के लिए है। तो array एक संदर्भ है जो मान द्वारा पारित किया गया है।

इस प्रकार, फ़ंक्शन के अंदर array में किए गए संशोधनों को वास्तव में int[] ऑब्जेक्ट पर लागू किया जाता है, जिस पर array संदर्भित करता है। और इसलिए वे संशोधन उन सभी संदर्भों के लिए दृश्यमान हैं जो उसी ऑब्जेक्ट को संदर्भित करते हैं। और इसमें उस संदर्भ को शामिल किया गया है जो कॉलर रखता है।

अब, अगर हम इस समारोह के कार्यान्वयन पर नज़र डालें:

public static void FirstDouble(int[] array) 
{ 
    //double each elements value 
    for (int i = 0; i < array.Length; i++) 
     array[i] *= 2; 

    //create new object and assign its reference to array 
    array = new int[] { 11, 12, 13 }; 
} 

वहाँ एक और समस्या है। for लूप केवल int[] के प्रत्येक तत्व को दोगुना करता है जो फ़ंक्शन पर पास हो जाता है। यह संशोधन है कि कॉलर देखता है।दूसरा भाग स्थानीय चर array पर एक नई int[] ऑब्जेक्ट का असाइनमेंट है। यह कॉलर को दिखाई नहीं दे रहा है क्योंकि यह संदर्भ array के संदर्भ को बदलना है। और चूंकि संदर्भ array मान द्वारा पारित किया गया है, कॉलर उस नई वस्तु को नहीं देखता है।

समारोह इस तरह घोषित किया गया था, तो:

public static void FirstDouble(ref int[] array) 

तो संदर्भ array संदर्भ द्वारा पारित कर दिया गया होता और फोन करने वाले नव निर्मित वस्तु { 11, 12, 13 } देखना होगा जब समारोह लौट आए।

+0

तो' सार्वजनिक स्थैतिक शून्य फर्स्ट डबल (रेफ इंट [] सरणी) ' – Jmyster

+0

@ जेमिस्टर से मेरा नवीनतम अपडेट कवर करने में क्या अंतर है। –

+0

नहीं यह कहना गलत है " परिवर्तनीय सरणी वास्तव में एक संदर्भ है "। इसका मतलब यह होगा कि कॉल-बाय-रेफरेंस शब्दावली का उपयोग करते समय इसे असाइन करने से कॉलर में मूल्य बदल जाएगा।" संदर्भ "के इस भ्रमित शब्द को ध्यान में रखते हुए सी ++ में संदर्भों के बारे में बात करना मुश्किल हो जाता है या सी # में 'ref/out', यही कारण है कि यह मेरा -1। –

2

सभी विधि पैरामीटर मान द्वारा पारित किए जाते हैं जब तक आप विशेष रूप से ref या out देखते हैं।

Arrays संदर्भ प्रकार हैं। इसका मतलब है कि आप मूल्य से संदर्भ पारित कर रहे हैं।

संदर्भ स्वयं ही तभी बदला जाता है जब आप इसे एक नई सरणी निर्दिष्ट करते हैं, यही कारण है कि उन असाइनमेंट कॉलर में दिखाई नहीं दे रहे हैं। जब आप ऑब्जेक्ट (यहां सरणी) को संदर्भित करते हैं और अंतर्निहित मान को संशोधित करते हैं तो आप चर बदल नहीं रहे हैं, बस यह क्या इंगित करता है। यह परिवर्तन कॉलर द्वारा भी "देखा" जाएगा, भले ही परिवर्तनीय (यानी यह क्या इंगित करता है) स्थिर रहता है।

1

शब्दों का भ्रमित उपयोग क्या है!

स्पष्ट करने के लिए,

1) एक विधि foo के लिए (int [] myArray), "मूल्य से एक संदर्भ (वस्तु) गुजर" वास्तव में अर्थ है "वस्तु का पता की एक प्रति गुजर (संदर्भ)"। इस 'प्रतिलिपि' का मूल्य, यानी। myArray, प्रारंभ में मूल वस्तु का पता (संदर्भ) है, जिसका अर्थ है कि यह मूल वस्तु को इंगित करता है। इसलिए, myArray द्वारा इंगित सामग्री में कोई भी परिवर्तन मूल ऑब्जेक्ट की सामग्री को प्रभावित करेगा।

हालांकि, चूंकि myArray का 'मान' एक प्रति है, इसलिए इस 'मान' में कोई भी परिवर्तन मूल वस्तु और न ही इसकी सामग्री को प्रभावित नहीं करेगा।

2) एक विधि foo (ref int [] refArray) के लिए, "संदर्भ द्वारा एक संदर्भ (ऑब्जेक्ट) पास करना" का अर्थ है "ऑब्जेक्ट का पता (संदर्भ) स्वयं (प्रतिलिपि नहीं) पास करना"। इसका मतलब है कि refArray वास्तव में ऑब्जेक्ट का मूल पता है, प्रतिलिपि नहीं। इसलिए, refArray के 'मान' में कोई भी परिवर्तन, या refArray द्वारा इंगित सामग्री मूल वस्तु पर प्रत्यक्ष परिवर्तन है।

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