2011-02-23 16 views
28

एक सवाल के बारे में Best practices for C# pattern validation में, उच्चतम जवाब मतदान का कहना है:सी # में अपरिवर्तनीय वस्तुएं कैसे बनाएं?

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

आप सी # में एक अपरिवर्तनीय वस्तु कैसे बनाते हैं? क्या आप बस readonly कीवर्ड का उपयोग करते हैं?

यदि आप अपनी इकाई फ्रेमवर्क जेनरेट मॉडल श्रेणी के निर्माता में मान्य करना चाहते हैं तो यह वास्तव में कैसे काम करेगा?

क्या यह नीचे दिखेगा?

public partial readonly Person 
{ 
    public Person() 
} 
+6

संभावित डुप्लिकेट [मैं एक अपरिवर्तनीय कक्षा कैसे बना सकता हूं?] (Http://stackoverflow.com/questions/352471/how-do-i-create-an-immutable-class) –

+4

डुप्लिकेट नहीं: क्योंकि यह प्रश्न सत्यापन के बारे में है, सृजन नहीं। – ChrisW

+3

मैं सत्यापन के बारे में पूछ रहा हूं, सृजन नहीं। –

उत्तर

66

यहां दिलचस्प सवाल टिप्पणियों से अपने सवाल यह है:

वस्तु किस तरह आपको लगता है कि आप कुछ बिंदु पर मूल्यों को संशोधित करने की जरूरत नहीं है के लिए होता है? मैं मॉडल मॉडल नहीं अनुमान लगा रहा हूं, सही? मुझे अपने डेटाबेस में किसी व्यक्ति का नाम बदलना पड़ा - यह इस विचार से फिट नहीं होगा।

ठीक है, उन चीजों पर विचार करें जो पहले से ही अपरिवर्तनीय हैं। संख्या अपरिवर्तनीय हैं। एक बार आपके पास संख्या 12 हो जाने के बाद, यह 12 है। आप इसे बदल नहीं सकते हैं। यदि आपके पास एक चर है जिसमें 12 है, तो आप चर के गुणों को 13 में बदल सकते हैं, लेकिन आप परिवर्तनीय बदल रहे हैं, संख्या 12 पर नहीं।

तारों के साथ ही। "एबीसी" "एबीसी" है, और यह कभी नहीं बदलता है। यदि आपके पास एक चर है जिसमें "एबीसी" है, तो आप इसे "abcd" में बदल सकते हैं, लेकिन यह "abc" नहीं बदलता है, जो चर बदलता है।

एक सूची के बारे में क्या? {12, "abc"} वह सूची है जो 12 है "इसके बाद" एबीसी ", और वह सूची कभी भी नहीं बदली जाती है। सूची {12, "abcd"} एक अलग-अलग सूची है।

और यही वह जगह है जहां चीजें रेल से निकलती हैं। क्योंकि सी # में आप इसे किसी भी तरह से कर सकते हैं। आप कह सकते हैं कि रेफरेंसियल पहचान उन दो सूचियों के बीच है यदि सूचियों को उनकी पहचान को बदले बिना अपनी सामग्री को म्यूट करने की अनुमति है।

जब आप "मॉडल" के बारे में बात करते हैं तो आप सिर पर नाखून दाहिनी ओर हिट करते हैं। क्या आप कुछ बदल रहे हैं जो बदलता है? यदि ऐसा है, तो संभवतः इसे एक प्रकार के साथ मॉडल करना संभव है जो बदलता है। इसका लाभ यह है कि मॉडल की विशेषताओं को मॉडल के मॉडल से मेल खाते हैं। नीचे की ओर यह है कि "रोलबैक" कार्यक्षमता जैसी कुछ करना बहुत मुश्किल हो जाता है, जहां आप एक बदलाव को पूर्ववत करते हैं।

यदि आप {12, "abc"} को {12, "abcd"} में बदलते हैं और फिर उत्परिवर्तन वापस रोल करना चाहते हैं, तो आप इसे कैसे करते हैं? यदि सूची अपरिवर्तनीय है तो आप केवल दोनों मानों को रखें और चुनें कि आप कौन सा "वर्तमान" मान बनना चाहते हैं। यदि सूची उत्परिवर्तनीय है तो आपको पूर्ववत तर्क को "पूर्ववत कार्य" के आसपास रखना होगा जो कि उत्परिवर्तन को पूर्ववत करने के बारे में जानता है।

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

2

एक अपरिवर्तनीय मूल्य वस्तु एक मूल्य वस्तु है जिसे बदला नहीं जा सकता है।

अचल स्थिति के प्रकार http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx

सभी की घोषणा

Immutable object pattern in C# - what do you think?

+0

ठीक है, इसलिए उत्तर का मूल आधार मैं इस प्रश्न का आधार बना रहा हूं, यह है कि एक बार जब यह निर्माता बनता है तो यह 100% प्रमाणित कोशेर और मान्य हो सकता है? आपके पास किस प्रकार की वस्तु होगी कि आपको किसी बिंदु पर मानों को संशोधित करने की आवश्यकता नहीं है? मैं मॉडल मॉडल नहीं अनुमान लगा रहा हूं, सही? मुझे अपने डेटाबेस में किसी व्यक्ति का नाम बदलना पड़ा - यह इस विचार से फिट नहीं होगा। –

9

पर एक नज़र डालें: आप अपने राज्य संशोधित नहीं कर सकते, तो आप नए लोगों को

बाहर चेक एरिक Lippert के ब्लॉग बनाने के लिए एक अपरिवर्तनीय वस्तु बनाने की दिशा में पढ़ा गया क्षेत्र एक अच्छा कदम है, लेकिन यह अकेला नहीं है। ऐसा इसलिए है क्योंकि एक पठनीय क्षेत्र अभी भी एक परिवर्तनीय वस्तु का संदर्भ हो सकता है।

सी # अपरिवर्तनीयता में संकलक द्वारा लागू नहीं किया जाता है। आपको बस सावधान रहना होगा।

+2

.. और कभी-कभी आप उन उत्परिवर्तनीय क्षेत्रों के एक अपरिवर्तनीय (या केवल-पढ़ने) संस्करण को वापस कर सकते हैं, उदा। ['सूची .sseadOnly'] (http://msdn.microsoft.com/en-us/library/e78dcd75.aspx) आपकी सूचियों के लिए। अंतिम पंक्ति के लिए – MasterMastic

+0

+1। वास्तव में सी # एक मौजूदा वस्तु से एक नई वस्तु बनाने के लिए चीनी प्रदान नहीं करता है, एक संपत्ति बदल जाती है। यहां तक ​​कि यदि एक वस्तु को अपरिवर्तनीय बनाना संभव था, तो एक नई प्रतिलिपि बनाना बहुत कठिन है। – nawfal

1

यदि आप अपनी इकाई फ्रेमवर्क जेनरेट मॉडल श्रेणी के निर्माता में मान्य करना चाहते हैं तो यह वास्तव में कैसे काम करेगा?

यह इस संदर्भ में काम नहीं करेगा क्योंकि ईएफ के लिए इकाई वर्ग के गुणों को सार्वजनिक होना आवश्यक है अन्यथा यह इसे तुरंत चालू नहीं कर सकता है।

लेकिन आपके कोड में अपरिवर्तनीय वस्तुओं का उपयोग करने के लिए आपका स्वागत है।

6

यह सवाल दो पहलू होते हैं:

  1. अपरिवर्तनीय प्रकार जब आप वस्तु का दृष्टांत
  2. अपरिवर्तनीय प्रकार जब एफई इन्स्तांत वस्तु

पहला पहलू इस तरह sturcture मांग:

public class MyClass 
{ 
    private readonly string _myString; 
    public string MyString 
    { 
    get 
    { 
     return _myString; 
    } 
    } 

    public MyClass(string myString) 
    { 
    // do some validation here 

    _myString = myString; 
    } 
} 

अब समस्या - ईएफ। ईएफ के लिए पैरामीटर रहित कन्स्ट्रक्टर की आवश्यकता होती है और ईएफ में गुणों पर सेटर्स होना चाहिए। मैंने बहुत ही question here से पूछा।

आपका प्रकार ध्यान देना चाहिए की तरह:

public class MyClass 
{ 
    private string _myString; 
    public string MyString 
    { 
    get 
    { 
     return _myString; 
    } 
    private set 
    { 
     _myString = value; 
    } 
    } 

    public MyClass(string myString) 
    { 
    // do some validation here 

    _myString = myString; 
    } 

    // Not sure if you can change accessibility of constructor - I can try it later 
    public MyClass() 
    {} 
} 

तुम भी MyString संपत्ति का निजी सेटर के बारे में एफई को सूचित करना चाहिए - इस edmx फ़ाइल में enitity के गुणों में कॉन्फ़िगर किया गया है। स्पष्ट रूप से कोई सत्यापन नहीं होगा जब ईएफ डीबी से वस्तुओं को पूरा करेगा। इसके अलावा आप ObjectContext.CreateObject (जैसे ऑब्जेक्ट भरने में सक्षम नहीं होंगे) जैसी विधियों का उपयोग करने में सक्षम नहीं होंगे।

इकाई ऑब्जेक्ट टी 4 टेम्पलेट और डिफ़ॉल्ट कोड पीढ़ी कारखाने विधि CreateMyClass को पैरामीटर के साथ निर्माता के बजाय बनाएं। पीओसीओ टी 4 टेम्पलेट फैक्टरी विधि उत्पन्न नहीं करता है।

मैंने पहले ईएफ कोड के साथ यह कोशिश नहीं की।

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