2012-10-29 11 views
7

से उनका उपयोग करके, निम्नलिखित कोड में, मैं कक्षा टेस्ट क्लास से एक विधि (कार्य) करने की कोशिश कर रहा हूं, मुख्य कार्यक्रम में कुछ चर के मूल्यों को वापस किए बिना उन्हें बदलने के लिए। चर टेस्ट क्लास कन्स्ट्रक्टर में संदर्भ द्वारा पारित किया जाता है।सी # - कन्स्ट्रक्टर के संदर्भ में गुजरने वाले पैरामीटर, विधि

class Program 
{ 
    static void Main(string[] args) 
    { 
     int a, b, c, d; 
     a = 5; b = 10; c = 20; d = 25; 
     Console.WriteLine("Main before TestClass: a=" + a + " b=" + b + " c=" + c + " d=" + d); 
     TestClass testObj = new TestClass(ref a,ref b,ref c,ref d); 
     testObj.Work(); 
     Console.WriteLine("Main after TestClass: a=" + a + " b=" + b + " c=" + c + " d=" + d); 
     Console.ReadLine(); 
    } 
} 

public class TestClass 
{ 
    int _a, _b, _c, _d; 
    public TestClass(ref int a, ref int b, ref int c, ref int d) 
    { 
     _a = a; _b = b; _c = c; _d = d; 
    } 

    public void Work() 
    { 
     Console.WriteLine("Work before changing: a=" + _a + " b=" + _b + " c=" + _c + " d=" + _d); 
     _a = 0; _b = 1; _c = 2; _d = 3; 
     Console.WriteLine("Work after changing: a=" + _a + " b=" + _b + " c=" + _c + " d=" + _d); 
    } 
} 

हालांकि यह कोड लौटाता है:

Main before TestClass: a=5 b=10 c=20 d=25 
Work before changing: a=5 b=10 c=20 d=25 
Work after changing: a=0 b=1 c=2 d=3 
Main after TestClass: a=5 b=10 c=20 d=25 

वहाँ विधि मुख्य कार्यक्रम में चर के मूल्यों को बदल के लिए कोई तरीका है? धन्यवाद!

+2

आपको '_a', आदि में * संदर्भ * स्टोर करना होगा, लेकिन आपने उन्हें अभी 'int' के रूप में घोषित किया है। जैसा कि यह पता चला है, सीएलआर इस अवधारणा का समर्थन नहीं करता है - आप * स्थानीय चर हैं जो संदर्भ हैं, लेकिन फ़ील्ड नहीं। [लेकिन सी # आपको ऐसे स्थानीय चर घोषित करने की भी अनुमति नहीं देता है] (http://blogs.msdn.com/b/ericlippert/archive/2011/06/23/ref-returns-and-ref-locals.aspx)। –

उत्तर

3

बदलावों के क्रम में Int32 से अधिक अपने स्वयं के रैपर बनाने, परिलक्षित होना क्योंकि एक बार मान वर्ग के क्षेत्रों के लिए आवंटित कर रहे हैं, तो अब वे संदर्भ, लेकिन Int32 के बजाय अलग-अलग विविधताएं हैं बंद बेहतर होगा । निम्नलिखित कोड पर विचार करें:

class Integer { 
    public int Value; 

    public Integer(int value) { 
     Value = value; 
    } 

    public override string ToString() { 
     return Value.ToString(); 
    } 
} 

class TestClass { 
    Integer _a, _b, _c, _d; 

    public TestClass(Integer a, Integer b, Integer c, Integer d) { 
     _a = a; 
     _b = b; 
     _c = c; 
     _d = d; 
    } 

    public void Work() { 
     _a.Value = 111; 
     _b.Value = 222; 
     _c.Value = 333; 
     _d.Value = 444; 
    } 
} 

तो अब आपके पास इंटीजर - इंट 32 पर एक रैपर वर्ग है।

Integer a = new Integer(0), b = new Integer(0), c = new Integer(0), d = new Integer(0); 
Console.WriteLine("a: {0}, b: {1}, c: {2}, d: {3}", a, b, c, d); 
new TestClass(a, b, c, d).Work(); 
Console.WriteLine("a: {0}, b: {1}, c: {2}, d: {3}", a, b, c, d); 

उत्पादन होता है:

a: 0, b: 0, c: 0, d: 0 
a: 111, b: 222, c: 333, d: 444 

तुम भी यह उपयोगी सी #, उदा वर्गों और structs के बारे में अधिक पढ़ने के लिए मिल सकता है उपयोग आप परिणाम लाएगा http://msdn.microsoft.com/en-us/library/ms173109.aspx। (Int32 एक struct, जबकि आपके मामले में आप शायद एक वर्ग की जरूरत है)

+0

धन्यवाद, यह काम किया! – panostra

3

संभव नहीं है। आप एक सदस्य के रूप में int के संदर्भ को संग्रहीत नहीं कर सकते हैं, और केवल int a एक प्रतिलिपि है - प्रतिलिपि में परिवर्तन मूल को नहीं बदलते हैं, जैसा आपने देखा है।

आप कक्षा के अंदर int को लपेट सकते हैं। आप कक्षा के संदर्भ को स्टोर कर सकते हैं और फिर उस पर काम कर सकते हैं।

public class IntWrapper 
{ 
    public IntWrapper(int val = 0) { Value = val; } 
    public int Value { get; set; } 
} 

static void Main(string[] args) 
{ 
    IntWrapper a = new IntWrapper(5); 
    TestClass testObj = new TestClass(a); 
    testObj.Work(); 
} 

public class TestClass 
{ 
    IntWrapper _a; 
    public TestClass(IntWrapper a) 
    { 
     _a = a; 
    } 

    public void Work() 
    { 
     Console.WriteLine("Work before changing: a=" + _a.Value); 
     _a.Value = 0; 
     Console.WriteLine("Work after changing: a=" + _a.Value); 
    } 
} 
2

जो आप करने की कोशिश कर रहे हैं वह नहीं किया जा सकता क्योंकि इसे इस तरह से उपयोग करने के लिए डिज़ाइन नहीं किया गया था। आपको पैरामीटर Work विधि में सीधे इसके बजाय जाना होगा।

testObj.Work(ref a, ref b, ref c, ref d); 
2

यह व्यवहार के कारण होता है:

int _a, _b, _c, _d; 
public TestClass(ref int a, ref int b, ref int c, ref int d) 
{ 
    _a = a; _b = b; _c = c; _d = d; 
} 

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

public void Work(ref int a, ref int b, ref int c, ref int d) 
{ 
    Console.WriteLine("Work before changing: a=" + a + " b=" + b + " c=" + c + " d=" + _d); 
    a = 0; b = 1; c = 2; d = 3; 
    Console.WriteLine("Work after changing: a=" + a + " b=" + b + " c=" + c + " d=" + _d); 
} 

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

रेफरी कीवर्ड के बारे में और अधिक समझने के लिए: ref (C# Reference) पर एक नज़र डालें।

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