2016-01-20 12 views
5

मैं सी # में structs और इंटरफेस के बीच अजीब अंतर के साथ आया (मेरे अनुसार)। इस इंटरफेस और struct पर विचार करें:सी # गेटर्स/सेटर्स और इंटरफेस में सेटर्स

public interface INumber 
{ 
    void ChangeNumber(int n); 
    void Log(); 
} 
public struct Number : INumber 
{ 
    private int n; 
    public void ChangeNumber(int n) 
    { 
     this.n = n; 
    } 
    public void Log() 
    { 
     Console.WriteLine(this.n); 
    } 
} 

जब मैं एक संपत्ति के रूप में संख्या के साथ एक नया वर्ग बनाने के लिए, ChangeNumber विधि का उपयोग करने के लिए 2 n बदल सकते हैं और प्रवेश का उपयोग करके संख्या मुद्रित करने के लिए, यह 0 के बजाय प्रिंट:

public class NumberContainer 
{ 
    public Number Number { get; set; } 
    public NumberContainer() 
    { 
     this.Number = new Number(); 
     this.Number.ChangeNumber(2); 
     this.Number.Log();    //prints 0... 
    } 
} 

थोड़ी देर बाद मुझे एहसास हुआ कि जब मैं this.Number.ChangeNumber(2); पर कॉल करता हूं, तो मैं वास्तव में एक नई वस्तु (गेटटर की वजह से) बनाता हूं और उस नंबर को 2 में बदलता हूं। लेकिन फिर मैंने संख्या को बदलकर कोड का थोड़ा सा बदल दिया एक एम्बर संपत्ति के लिए संपत्ति:

public class NumberContainer 
{ 
    public INumber Number { get; set; } 
    public NumberContainer() 
    { 
     this.Number = new Number(); 
     this.Number.ChangeNumber(2); 
     this.Number.Log();    //prints 2! 
    } 
} 

इस मामले में, यह 2 प्रिंट करता है! ये क्यों हो रहा है? क्या स्ट्रक्चर का एक ही प्रिंसिपल इंटरफ़ेस पर लागू नहीं होता है?

+1

जब इसे इंटरफेस के रूप में संदर्भित किया जाता है तो यह बॉक्सिंग हो जाता है। लेकिन आम तौर पर structs को अपरिवर्तनीय बनाने के लिए सबसे अच्छा है या यदि आपको म्यूटेबिलिटी की आवश्यकता है तो आपको इसे कक्षा बनाना चाहिए। – juharr

उत्तर

4

अंतर यह है कि struct एक मान प्रकार है, जहां interface (कक्षा या एक struct द्वारा कार्यान्वित किया जा सकता है) के लिए एक संदर्भ प्रकार है के रूप में इस्तेमाल किया जाता है।

इससे आपके उदाहरण में एक बड़ा अंतर आता है। पहले मामले में आप क्या कर रहे हैं this.Number पर कॉल का अर्थ है "मुझे नंबर का मूल्य प्राप्त करें" - जिसका अर्थ है कि यह स्टैक पर मान खींचता है, और स्टैक पर (अनामित) चर, जो कहीं भी संग्रहीत नहीं होता है, संशोधित हो जाता है।

अन्य मामले में, इंटरफ़ेस एक संदर्भ प्रकार है - जिसका अर्थ है, यह जो भी उसके पते पर संग्रहीत होता है उसे संशोधित करता है और इसे संशोधित करता है।

आम तौर पर मैं एक म्यूटेबल struct (जैसा कि पहले से ही टिप्पणियों में उल्लिखित है) का सुझाव नहीं देगा।

आप इस विषय पर और अधिक पढ़ सकते हैं उदा। यहां: Why are mutable structs “evil”?

2

यह NumberContainer कक्षा में ऑटो प्रॉपर्टी के कारण होता है, जब आप संपत्ति तक पहुंचते हैं तो आपको हमेशा मूल्य की एक प्रति प्राप्त होती है।

यदि आप किसी क्षेत्र में संपत्ति बदलते हैं, तो यह अपेक्षित के रूप में कार्य करता है। याद रखें कि ऑटोप्रोपर्टी केवल विधियों की जोड़ी है, और किसी भी विधि से लौटा/पास होने पर उस मान प्रकार की प्रतिलिपि बनाई जाती है।

जब आप आप वास्तव में बुला रहे हैं

 this.Number.ChangeNumber(2); 
     this.Number.Log();    //prints 0... 

बुला रहे हैं:

this.getNumber() // returns copy of value type 
     .ChangeNumber(2); // executes op on that copy 

    this.getNumber() 
     .Log(); 

आप इंटरफ़ेस का उपयोग कर रहे हैं जब आप एक वस्तु के संदर्भ में लौट रहे हैं तो संचालन हमेशा एक ही वस्तु पर प्रदर्शन कर रहे हैं।

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