2009-07-24 22 views
11

मार्टिन फाउलर की पुनर्रचना अशक्त वस्तुओं बनाने की चर्चामैं सी # में एक अशक्त वस्तु

if (myObject == null) 

परीक्षण से बचने का कैसे बना सकता हूँ। ऐसा करने का सही तरीका क्या है? मेरा प्रयास "कन्स्ट्रक्टर में आभासी सदस्य कॉल" नियम का उल्लंघन करता है। यहाँ यह पर मेरे प्रयास है:

public class Animal 
{ 
    public virtual string Name { get; set; } 
    public virtual string Species { get; set; } 
    public virtual bool IsNull 
    { 
     get { return false; } 
    } 
} 

public sealed class NullAnimal : Animal 
{ 
    public override string Name 
    { 
     get{ return "NULL"; } 
     set { } 
    } 
    public override string Species 
    { 
     get { return "NULL"; } 
     set { } 
    } 
    public virtual bool IsNull 
    { 
     get { return true; } 
    } 
} 
+3

आप जिस समस्या को हल करने की कोशिश कर रहे हैं? शून्य संदर्भों के साथ क्या गलत है, बिल्कुल? – spoulson

+2

http://www.refactoring.com/catalog/introduceNullObject.html – Sisiutl

+0

नलएनिमल कक्षा में आपकी IsNull संपत्ति एक ओवरराइड होना चाहिए, वर्चुअल नहीं। – TGnat

उत्तर

11

मुझे लगता है कि में Wyatt Barnett's answer से सहमत करने के लिए जब "अशक्त" वस्तुओं के इन प्रकार बनाने आप संयम दिखाना चाहिए होते हैं। उस ने कहा, ऐसा करने के कुछ अच्छे कारण हैं। अवसर पर।

मैं Supertux's answer से भी सहमत हूं कि एक शून्य वस्तु के पूरे बिंदु को यह जांचने की आवश्यकता नहीं है कि यह शून्य है या नहीं, तो आपको IsNull संपत्ति खोनी चाहिए। यदि आपको वास्तव में लगता है कि आपको IsNull संपत्ति की आवश्यकता है, तो फिर वैट की प्रतिक्रिया को फिर से पढ़ें और पुनर्विचार करें।

और अधिक जानकारी के लिए CraigTP for the nice links धन्यवाद। अच्छी चीज़।

अब मैं मानता हूं कि आपके वास्तविक कोड में आपके पास वास्तव में एक निर्माता है जो नाम या प्रजातियों के मूल्य निर्धारित करने का प्रयास कर रहा है (जो भी आपका वास्तविक कोड समकक्ष कहा जा सकता है)। अन्यथा, आपको "कन्स्ट्रक्टर में आभासी सदस्य कॉल" चेतावनी/त्रुटि क्यों मिलेगी? न्यूफैंगल्ड माईप्रोपर्टी का उपयोग करते समय मैंने कुछ समान समस्याओं में भाग लिया है {प्राप्त करें; सेट; } खुद को शॉर्टकट (विशेष रूप से जब structs में उपयोग किया जाता है, और मुझे serialization संस्करण के बारे में शुरू नहीं करते हैं)। आपका समाधान शॉर्टकट का उपयोग नहीं करना है, बल्कि इसके बजाय पुराने तरीके से करें।

public class Animal { 
    protected Animal() { } 

    public Animal(string name, string species) { 
     _Name = name; 
     _Species = species; 
    } 

    public virtual string Name { 
     get { return _Name; } 
     set { _Name = value; } 
    } 
    private string _Name; 

    public virtual string Species { 
     get { return _Species; } 
     set { _Species = value; } 
    } 
    private string _Species; 
} 

public sealed class NullAnimal : Animal { 
    public override string Name { 
     get { return String.Empty; } 
     set { } 
    } 
    public override string Species { 
     get { return String.Empty; } 
     set { } 
    } 
} 

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

जितना अधिक मैं {get; सेट; } शॉर्टकट, जितना अधिक मैं इसे नापसंद करता हूं।

22

जाओ दर्द है कि इस तरह DBNull के रूप में दिलचस्प अवधारणाओं,, का कारण है की राशि को देखने और के बारे में लगता है कि अगर यह वास्तव में एक अच्छा विचार है।

Protip: यदि आप लगातार नल संदर्भ के लिए जाँच कर रहे हैं, तो आप शायद एपीआई थोड़ा ढेर के शीर्ष के पास अशक्त वस्तुओं बाधा मदद करने के लिए पुनर्विचार करना चाहिए।

प्रोटिप II: अप्रत्याशित शून्य होने पर कुछ अपवाद फेंकना वास्तव में ठीक और बेवकूफ है। चीजें बूम होनी चाहिए यदि आपके पास नल हैं जहां शून्य नहीं होना चाहिए।

+7

+1। नल पैटर्न एक विरोधी पैटर्न आईएमओ है। अवांछित नल के लिए फेंको और जब उन्हें अनुमति दी जाती है तो नल की जांच करें। – Randolpho

+1

NullObject पैटर्न का विचार यह है कि चीजें तेजी से नहीं बढ़ती हैं - खासकर उत्पादक में। – Supertux

+0

@ वैट: http://jeremyjarrell.com/archive/2007/08/01/46.aspx शून्य वस्तुओं के लाभों का एक अच्छा प्रदर्शन है ... लेकिन मैं व्यक्तिगत रूप से उनके बारे में एक बड़ा प्रशंसक नहीं हूं। – Brian

2

कृपया दोनों डिज़ाइन पैटर्न ही (अशक्त वस्तु डिजाइन पैटर्न) और एक कार्यान्वयन के लिए इन लिंक (सी # में) देखें:

डिजाइन पैटर्न:

Null Object pattern - Wikipedia
Null Object Design Pattern
Introduce Null Object (contains some implementation code)

एक कार्यान्वयन:

The Null Object Pattern

+0

आपका अंतिम लिंक मृत दिखता है। – LarsTech

+0

@ लार्सटेक मैंने पृष्ठ के [इंटरनेट आर्काइव की वेबैक मशीन] (http://archive.org/web/) कैश को इंगित करने के लिए अंतिम लिंक अपडेट किया है। – CraigTP

+0

बीटीडब्ल्यू, मैं नीचे वोट नहीं था। – LarsTech

3

अशक्त वस्तु पैटर्न की बात यह है कि यह एक दुर्घटना या त्रुटि को रोकने के लिए एक अशक्त जांच की आवश्यकता नहीं है।

उदाहरण के लिए यदि आप प्रजाति संपत्ति पर कार्रवाई करने की कोशिश की और यह शून्य था - यह एक त्रुटि का कारण होगा।

तो, आप एक IsNull विधि आवश्यकता नहीं होनी चाहिए, बस गेटर में कुछ है कि एप्लिकेशन के क्रैश होने का कारण नहीं बनेगा/त्रुटि जैसे लौट:

public class Animal 
{ 
    public virtual string Name { get; set; } 
    public virtual string Species { get; set; } 
} 

public sealed class NullAnimal : Animal 
{ 
    public override string Name 
    { 
     get{ return string.Empty; } 
     set { ; } 
    } 
    public override string Species 
    { 
     get { return string.Empty; } 
     set { ; } 
    } 
} 
+0

ठीक है, लेकिन यह अभी भी कन्स्ट्रक्टर नियम में आभासी सदस्य कॉल का उल्लंघन करता है। – Sisiutl

+0

तकनीकी रूप से नहीं, क्योंकि कोई कन्स्ट्रक्टर नहीं है। –

2

आप केवल इस दृष्टिकोण का उपयोग करता है, तो यह उचित है । एक पशु वस्तु का आपका उदाहरण एक अच्छा उदाहरण नहीं हो सकता है क्योंकि यह एक उचित मामला नहीं पेश करता है जहां आप इस दृष्टिकोण का उपयोग करेंगे। उदाहरण के लिए:

Animal animal = new Animal(); 

if (animal.tail == null) 
{ 
    //do nothing because wagging a tail that doesn't exist may crash the program 
} 
else 
{ 
    animal.wagTail(); 
} 

इस उदाहरण में, आप पशु वस्तु का निर्माण इतना है कि यदि जानवर एक पूंछ नहीं है, इसे सफलतापूर्वक वेग्टेल() आदेश दुर्घटनाग्रस्त बिना संभाल कर सकते हैं चाहिए।

Class Animal 
{ 
    Tail tail; 

    void wagTail() 
    { 
     if (this.tail == null) 
     { 
      //do nothing 
     } 
     else 
     { 
      this.tail.doTheWag(); 
     } 
    } 
} 

अब आप एक अशक्त जांच की जरूरत नहीं है, लेकिन सिर्फ animal.wagTail (कॉल कर सकते हैं) क्या जानवर एक पूंछ है या नहीं की परवाह किए बिना।

+0

अनियंत्रित/चेहरे का –

+1

मैं ऑनलाइन हूं और बेवकूफ की तरह दिखता हूं। और क्या नया है? – tyriker

+0

यह आपके लिए तय किया गया है। –

0

मैं यहां कुछ दिलचस्प विवरण का उल्लेख करना चाहता हूं। अपनी कक्षा को देखो। क्या इसमें कोई तर्क है? यह एक वर्ग नहीं है, यह एक डेटा संरचना है। आप जो करने की कोशिश कर रहे हैं वह शून्य वस्तु ऑब्जेक्ट पैटर्न को लागू करने के लिए लागू नहीं है। कक्षा संरचना वर्गों की तुलना में मूल्य प्रकार के करीब है। आपकी समस्या को हल करने के लिए सामने शून्य जांच सही हो सकती है। शून्य ऑब्जेक्ट पैटर्न ऐसा कुछ नहीं है जिसे आपको हमेशा पालन करना चाहिए। नल ऑब्जेक्ट पैटर्न एक ऐसी चीज है जिसका उपयोग आप लिस्कोव के प्रतिस्थापन सिद्धांत उल्लंघन से बचने के लिए कर सकते हैं, जो किसी वर्ग को प्रदर्शित करने के लिए नहीं है, क्योंकि शून्य एक वर्ग के लिए उचित प्रतिस्थापन नहीं है क्योंकि यह एक मूल्य है, लेकिन कक्षा नहीं है। लेकिन मूल्य प्रकार और डेटा संरचनाओं के साथ चीजें अलग-अलग हैं। शून्य मूल्य है! तो इस मामले में शून्य जांच करने के लिए सही बात है।

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