c# - अपरिवर्तनीय structs के लिए सार्वजनिक readonly क्षेत्रों का उपयोग कर काम करता है?




immutability (4)

कंपाइलर readonly फ़ील्ड के साथ-साथ केवल पढ़ने योग्य गुणों को असाइनमेंट को रोक देगा।

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

क्या यह अपरिवर्तनीय structs घोषित करने का एक उचित तरीका है?

public struct Pair
{
    public readonly int x;
    public readonly int y;

    // Constructor and stuff
}

मैं नहीं सोच सकता कि यह समस्याओं में क्यों चलेगा, लेकिन मैं बस यह सुनिश्चित करने के लिए पूछना चाहता था।

इस उदाहरण में, मैंने इन्ट्स का इस्तेमाल किया। क्या होगा यदि मैंने इसके बजाय कक्षा का उपयोग किया, लेकिन वह वर्ग भी अपरिवर्तनीय है, तो ऐसा? यह भी ठीक काम करना चाहिए, है ना?

public struct Pair
{
    public readonly (immutableClass) x;
    public readonly (immutableClass) y;

    // Constructor and stuff
}

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


यदि आप structs का उपयोग करने जा रहे हैं, तो उन्हें अपरिवर्तनीय बनाने का सबसे अच्छा अभ्यास है।

सभी क्षेत्रों को केवल पढ़ने के लिए (1) दस्तावेज की मदद करने का एक शानदार तरीका है कि संरचना अपरिवर्तनीय है, और (2) आकस्मिक उत्परिवर्तन को रोकें।

हालांकि, एक झुर्री है, जो वास्तव में एक अजीब संयोग में मैं अगले सप्ताह के बारे में ब्लॉगिंग पर योजना बना रहा था। यही है: एक संरचना क्षेत्र पर केवल एक झूठ है । एक उम्मीद करता है कि एक पाठक क्षेत्र बदल नहीं सकता है, लेकिन निश्चित रूप से यह कर सकता है। एक संरचना क्षेत्र पर "पठनीय" घोषणा अपने खाते में कोई पैसा नहीं होने के साथ घोषणा लेखन जांच है। एक संरचना के भंडारण का स्वामित्व नहीं है, और यह वह भंडारण है जो उत्परिवर्तित कर सकता है।

उदाहरण के लिए, आइए अपनी संरचना लें:

public struct Pair
{
    public readonly int x;
    public readonly int y;
    public Pair(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
    public void M(ref Pair p)
    {
        int oldX = x;
        int oldY = y;
        // Something happens here
        Debug.Assert(x == oldX);
        Debug.Assert(y == oldY);
    }
}

क्या ऐसा कुछ भी हो सकता है जो "यहां कुछ होता है" जो डीबग दावे का उल्लंघन करने का कारण बनता है? ज़रूर।

    public void M(ref Pair p)
    {
        int oldX = this.x;
        int oldY = this.y;
        p = new Pair(0, 0);
        Debug.Assert(this.x == oldX);
        Debug.Assert(this.y == oldY);
    }
...
    Pair myPair = new Pair(10, 20);
    myPair.M(ref myPair);

और अब क्या होता है? दावा का उल्लंघन किया जाता है! "यह" और "पी" एक ही भंडारण स्थान का संदर्भ लें। भंडारण स्थान को उत्परिवर्तित किया जाता है, और इसलिए "इस" की सामग्री उत्परिवर्तित होती है क्योंकि वे एक ही चीज़ हैं। संरचना x और y के केवल-पढ़ने-कोस को लागू करने में सक्षम नहीं है क्योंकि संरचना में भंडारण का स्वामित्व नहीं है; भंडारण एक स्थानीय चर है जो जितना चाहें म्यूटेट करने के लिए स्वतंत्र है।

आप इनवेरिएंट पर भरोसा नहीं कर सकते कि एक संरचना में एक पाठक क्षेत्र को बदलने के लिए कभी नहीं देखा जाता है; एकमात्र चीज जिस पर आप भरोसा कर सकते हैं वह यह है कि आप उस कोड को नहीं लिख सकते जो सीधे इसे बदलता है। लेकिन इस तरह के छोटे चुस्त काम के साथ आप अप्रत्यक्ष रूप से इसे बदल सकते हैं जो आप चाहते हैं।

इस मुद्दे पर जो डफी के उत्कृष्ट ब्लॉग आलेख को भी देखें:

http://joeduffyblog.com/2010/07/01/when-is-a-readonly-field-not-readonly/


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


अपने डेटा वर्ग के अंदर एक बिल्डर वर्ग बनाने के बारे में कैसे। डेटा क्लास में सभी सेटर्स निजी होंगे और केवल निर्माता ही उन्हें सेट कर पाएंगे।

public class DoSomeActionParameters
    {
        public string A { get; private set; }
        public string B  { get; private set; }
        public DateTime C { get; private set; }
        public OtherEnum D  { get; private set; }
        public string E  { get; private set; }
        public string F  { get; private set; }

        public class Builder
        {
            DoSomeActionParameters obj = new DoSomeActionParameters();

            public string A
            {
                set { obj.A = value; }
            }
            public string B
            {
                set { obj.B = value; }
            }
            public DateTime C
            {
                set { obj.C = value; }
            }
            public OtherEnum D
            {
                set { obj.D = value; }
            }
            public string E
            {
                set { obj.E = value; }
            }
            public string F
            {
                set { obj.F = value; }
            }

            public DoSomeActionParameters Build()
            {
                return obj;
            }
        }
    }

    public class Example
    {

        private void DoSth()
        {
            var data = new DoSomeActionParameters.Builder()
            {
                A = "",
                B = "",
                C = DateTime.Now,
                D = testc,
                E = "",
                F = ""
            }.Build();
        }
    }




c# struct immutability