2013-09-06 5 views
10

निम्नलिखित विशिष्ट परिदृश्य पर विचार करें:के साथ नल ऑब्जेक्ट्स Instantiating ?? ऑपरेटर

if(anObject == null) 
{ 
anObject = new AClass(); 
} 

मैं सोच रहा हूँ क्या उपयोग करके निम्न प्रतिस्थापन के बारे में सोचा है ?? ऑपरेटर:

anObject = anObject ?? new AClass(); 

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

क्या यह करने के लिए एक उचित बात है, या क्या कोई बेहतर शॉर्टेंड है कि मुझे याद आ रही है? या शायद, "यह तीन लाइनें है, इसे खत्म करो!"

+2

दोनों आम हैं। –

+7

यदि यह कोड गंध होगा, तो इसे पहले स्थान पर पेश नहीं किया जाएगा। दूसरा रूप अधिक संक्षिप्त है और इसे प्राथमिकता दी जानी चाहिए। –

+0

@JeroenVannevel: सवाल यह नहीं है कि '??' ऑपरेटर कोड-गंध है, लेकिन क्या इसका एक अभिव्यक्ति में उपयोग किया जाता है जिसे उसके ऑपरेंड में से एक के रूप में पारित किया गया है, कोड-गंध है। –

उत्तर

12

अद्यतन:

ओ आर मैपर के रूप में बताया गया है, सवाल यह है कि स्वयं काम एक कोड-गंध है के साथ क्या करना है। यह मेरी पुस्तक में 6 और दो 3 एस है। असाइनमेंट शायद ही एक महंगी ऑपरेशन है, और आप इसे अधिकांश गणित ऑपरेटरों के साथ किसी भी दर पर अन्य क्षेत्रों में करते हैं।

मुझे लगता है कि यह कोड गंध नहीं है।


मैं सभी आलसी वस्तुओं के लिए समय (अपने उदाहरण पर एक मामूली बदलाव) कि कार्य करें:

return _myClass ?? (_myClass = new MyClass()); 

मुझे लगता है कि यह ठीक है। विचित्र रूप से पर्याप्त मैं Lazy<T> का उपयोग नहीं करता ... यकीन नहीं क्यों, लेकिन फिर मैं अक्सर आलसी वस्तुओं को नहीं बनाता। Lazy<T> इसके इरादे में अधिक अभिव्यक्तिपूर्ण है, जैसा कि आप पढ़ सकते हैं कि आइटम आलसी रूप से तत्काल है, लेकिन तकनीकी रूप से यह किसी मौजूदा आइटम पर object ओवरहेड जोड़ता है। मैं वास्तव में किसी भी तरह से वास्तव में चिंता नहीं करता हूं।

"इसे प्राप्त करने" के लिए, मुझे लगता है कि यह शायद उस श्रेणी में पड़ता है। मुझे लगता है कि इस मामले में प्रत्येक के लिए खुद को।

+1

धन्यवाद एक बहुत अच्छा विचार है कि मैं 12 मिनट के बाद जवाब को चिह्नित करूंगा, अब मैं धन्यवाद नहीं दे सकता। –

+1

मुझे दावा नहीं है कि इनमें से कोई भी कोड-गंध है। मेरी उपर्युक्त टिप्पणी में, मैं बस यह इंगित करना चाहता हूं कि * "इसे" पेश किया गया है या नहीं * * * यह * '?? ऑपरेटर होना - अप्रासंगिक है, क्योंकि सवाल यह नहीं सोचता कि ऑपरेटर स्वयं कोड-गंध है, लेकिन सवाल में दिखाए जाने का इसका विशेष तरीका है। –

+1

@ O.R.Mapper क्षमा करें मैं फिर से शब्द दूंगा, जो मैं कहना चाहता था, क्या आपने हाइलाइट किया है कि सवाल स्वयं-असाइनमेंट के बारे में था और क्या वह कोड गंध था। मेरी गलती। –

6

अभिव्यक्ति के परिणाम को उसी वैरिएबल पर वापस निर्दिष्ट किए बिना - उदा। a = b ?? new AClass(); - उस पैटर्न ठीक है और यह एक "fallback" नया डिफ़ॉल्ट उदाहरण की तरह कुछ के लिए कार्य करता है:

private MyClass anObject; 

// ... 

(anObject ?? new MyClass()).DoSomething(); 

इस मामले में, नव निर्मित वस्तु बाद में पुन: उपयोग के लिए संग्रहीत नहीं है।

जब एक ही चर को बताए, ऐसा लगता है आप lazily कुछ आरंभ कर रहे हैं, जो मामले Lazy<T> का उपयोग करने में जाने के लिए अधिक अर्थपूर्ण तरीका होगा:

private Lazy<MyClass> anObject = new Lazy<MyClass>(); 

// ... 

anObject.Value.DoSomething(); 

उदाहरण नवीनतम जब बना दी जाएगी अंतिम पंक्ति निष्पादित करता है।

+2

हालांकि मैं सहमत हूं कि 'आलसी ' अधिक अभिव्यक्तिपूर्ण और स्पष्ट रूप से कार्य के लिए डिज़ाइन किया गया है, मैं थोड़ी देर से सोचता हूं कि जब मैं "जाने का पसंदीदा तरीका" पढ़ता हूं जैसे कि यह सार्वभौमिक रूप से सहमत है। –

+1

@AdamHouldsworth: आप सही हैं, मैंने जवाब में शब्दों की अपनी पसंद में सुधार किया है। उस सुधार के लिए –

+1

+1। मैं आमतौर पर "सर्वोत्तम अभ्यास" प्रश्नों से बाहर रहना चाहता हूं, लेकिन मुझे लगा कि यह सबसे अधिक हानिकारक था। यदि आप "मानक" के खिलाफ जाते हैं तो आप बहुत अधिक फ्लाक करते हैं: -P –

1
void Main() 
{ 
    AClass anObject = null; 

    // option A 
    if (anObject == null) 
    { 
     anObject = new AClass(); 
    } 
    // option B 
    anObject = anObject ? new AClass(); 
} 

विकल्प बी के अनुकूलित आईएल कोड के साथ विकल्प एक तुलना:

Option A       Option B       Description 
IL_0000: ldnull     IL_0000: ldnull     // Push a null reference on the stack. 
IL_0001: stloc.0  // anObject IL_0001: stloc.0  // anObject // Pop a value from stack into local variable 0. 
IL_0002: ldloc.0  // anObject IL_0002: ldloc.0  // anObject // Load local variable 0 onto stack 
            IL_0003: dup      // Duplicate the value on the top of the stack. 
IL_0003: brtrue.s IL_000B  IL_0004: brtrue.s IL_000C  // Branch to target if value is non-zero 
            IL_0006: pop      // Pop value from the stack 
IL_0005: newobj  AClass..ctor IL_0007: newobj  AClass..ctor // Allocate an uninitialized object or value type and call ctor 
IL_000A: stloc.0  // anObject IL_000C: stloc.0  // anObject // Pop a value from stack into local variable 0. 

आप देख सकते हैं वहाँ बहुत कम दोनों के बीच अंतर है - परिणाम कुछ और में विकल्प बी (त्रिगुट ऑपरेटर का उपयोग) ढेर संचालन।

जब तक आपके कंप्यूटर घड़ी की कल पर चलता है आप अपने अंतिम कोड में कोई अंतर दिखाई कई चीजों के साथ के रूप में तो होगा - जो भी अपने कोड के लिए सबसे अधिक पठनीय है।

विधि 1 गैर लेज़ी:

+2

तो क्या यह सिर्फ यह कह रहा है कि सहकर्मी ऑपरेटर अधिक संक्षिप्त आईएल उत्पन्न करता है?यह सुनिश्चित नहीं है कि स्पष्टीकरण के बिना यह अकेले कैसे जवाब देता है, अकेले इसे दो बार कैसे बढ़ाया गया है ... –

+1

-1 क्योंकि अप्रत्याशित आईएल की तुलना किसी भी तरह व्यर्थ है। – hvd

+0

अंक उठाए गए ... उत्तर में सुधार ... –

0

पैटर्न है कि मैं WPF दृश्य मॉडल में इस्तेमाल किया (जो वह जगह है जहाँ मैं इस पैटर्न ज्यादातर इस्तेमाल किया देखें) देखा है के एक जोड़े हैं

public class ViewModel 
{ 
    private readonly SomeValue _value; 

    public ViewModel() 
    { 
     _value = new SomeValue(); 
    } 

    public SomeValue Value { get { return _value; } } 
} 

विधि 1 आलसी:

public class ViewModel 
{ 
    private readonly Lazy<SomeValue> _value = new Lazy<SomeValue>(() => new SomeValue()); 

    public SomeValue Value { get { return _value.Value; } } 
} 

विधि 2:

public class ViewModel 
{ 
    private SomeValue _value; 

    public SomeValue Value { get { return _value ?? (_value = new SomeValue()); } } 
} 

विधि 1 और विधि 2 के बीच प्रमुख अंतर यह है कि वस्तु कब और कैसे बनाई जाती है। विधि 1 आलसी Lazy(T) का उपयोग करता है जो सृजन के लिए ओवरहेड जोड़ता है। यह केवल बड़ी वस्तुओं के लिए वास्तव में जरूरी है और डब्ल्यूपीएफ मॉडल बहुत भारी भारोत्तोलन नहीं करते हैं। ऑब्जेक्ट सृजन को उचित रखने के लिए बड़ी वस्तुएं आंतरिक रूप से आलस्य का लाभ ले सकती हैं।

विधि 1 आलसी और विधि 2 बहुत बड़ा है जब दृश्य बड़ा होता है। यूआई को उत्तरदायी रखा जाना चाहिए, इसलिए ऑब्जेक्ट सृजन को बेहतर बनाना एक बेहतर उपयोगकर्ता अनुभव प्रदान करता है। जब जटिल वस्तुओं के साथ बड़ी वस्तुएं शामिल होती हैं तो यह आवश्यक साबित होगी।

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