2009-11-25 5 views
6

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

बेहतर तरीका कौन सा है?

public int? DoSomethingWonderful() 

या

public bool DoSomethingWonderful(out int parameter) 

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

संपादित करें: स्पष्टीकरण, यह कोड एक काले बॉक्स से बात करता है (इसे क्लाउड कॉल करें। नहीं, एक काला बॉक्स। नहीं, प्रतीक्षा करें। क्लाउड। हाँ)। मुझे परवाह नहीं है क्यों यह विफल रहा। मुझे सिर्फ यह जानना होगा कि मेरे पास वैध मान है या नहीं।

उत्तर

12

मैं नल संस्करण बेहतर लगता है तो इसलिए कि आप उपयोग कर सकते हैं नल coalesce ऑपरेटर ?? उस पर, जैसे:

int reallyTerrible = 0; 
var mightBeWonderful = DoSomethingWonderful() ?? reallyTerrible; 
+2

बस जो मैं लिखने जा रहा था। इसका मतलब यह भी है कि यदि आपको इसकी आवश्यकता नहीं है तो आपको एक अलग चर घोषित करने की आवश्यकता नहीं है। असल में यह अधिक तरल पदार्थ अभिव्यक्तियों की अनुमति देता है। –

+4

वाह !!!! मैंने सिर्फ जॉन स्कीट को एक एसओ जवाब पर छूट दी !!! मैं आज रात सो नहीं पाऊंगा! – Manu

+0

यह वास्तव में अच्छा है। यह इस बात पर निर्भर करता है कि इस नल को कैसे संभाला जाना चाहिए। प्रश्न में "यह भी असफल हो सकता है" के कारण, मैंने माना कि यह एक त्रुटि है और इसे इस तरह अनदेखा नहीं किया जाना चाहिए। यदि यह कर सकता है, तो यह दृष्टिकोण निश्चित रूप से सबसे अच्छा है। –

2

मैं की तरह नेट पुस्तकालय में कुछ स्थान पर इस्तेमाल किया पैटर्न का पालन होगा:

bool int.TryParse(string s, out value) 
bool Dictionary.TryGetValue(T1 key, out T2 value) 

तो मैं कहूंगा कि:

public bool TryDoSomethingWonderful(out int parameter) 
0

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

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

2

मैं दूसरे का प्रयोग करेंगे, क्योंकि मैं शायद अभी जानना चाहते हैं कि कॉल सफल रहा है, और उस मामले में मैं नहीं बल्कि

int x; 
if(DoSomethingWonderful(out x)) 
{ 
    SomethingElse(x); 
} 

से

int? x = DoSomethingWonderful(); 
if(x.HasValue) 
{ 
    SomethingElse(x.Value); 
} 
+0

अपने कोड स्निपेट तुलनीय बनाने के लिए आपको पहले स्निपेट में x घोषित करना चाहिए। –

+0

दरअसल, आपको पहले उदाहरण में उपयोग करने से पहले एक्स चर घोषित करने की आवश्यकता होगी, इसलिए कोड की पंक्तियों की संख्या समान होगी। –

+0

अच्छा, ऐसा इसलिए हो सकता है क्योंकि आप अजीब उपयोग की तुलना कर रहे हैं। कैसे 'if (x! = Null) {SomethingElse ((int) x); } '? – Joren

2

लिखते थे यह वास्तव में पर निर्भर करता है तुम क्या कर रहे हो।

क्या कोई सार्थक उत्तर नहीं है? यदि नहीं, तो मैं bool TryDoSomethingWonderful(out int) विधि कॉल पसंद करूंगा। यह फ्रेमवर्क के साथ मेल खाता है।

अगर, हालांकि, अशक्त एक सार्थक वापसी मान, है पूर्णांक लौटने? समझ में आता है।

0

आप बल्कि तो एक कोशिश पकड़ का उपयोग करना चाहिए। ऐसा लगता है जैसे कॉलर नहीं जानता कि क्या हो सकता है?

हम दोनों bool और बाहर की जाँच करना चाहिए, या मैं दोनों रिटर्न बातिल और वास्तविक वापसी जांच होनी चाहिए।

विधि क्या यह होना चाहिए करते हैं, और इस मामले में जहां यह असफल है, फोन करने वाले जानते हैं कि यह विफल रहा है, और फोन करने वाले के रूप में hanlde requied।

5

यह आप कैसे लगता है कि फोन करने कैसा दिखना चाहिए पर निर्भर करता है। और इसलिए आपके फ़ंक्शन का उपयोग किस लिए किया जाता है।

आमतौर पर, आप तर्क बाहर से बचना चाहिए।

int parameter; 
if (DoSomething(out paramameter)) 
{ 
    // use parameter 
} 

आप एक नल पूर्णांक उपलब्ध हो तो उसे इस प्रकार दिखाई देगा:

int? result = DoSomething(); 
if (result != null) 
{ 
    // use result 
} 

यह कुछ हद तक बेहतर है क्योंकि आप डॉन 'दूसरी ओर, इसे इस तरह कोड के लिए अच्छा हो सकता है टी के बाहर तर्क नहीं है, लेकिन कोड जो निर्णय लेता है कि समारोह सफल हुआ है, वह बहुत स्पष्ट नहीं दिखता है।

भूल वहाँ एक और विकल्प है कि नहीं है: exeptions का उपयोग करें। केवल तभी ऐसा करें जब आपका कार्य विफल हो जाए, वास्तव में एक असाधारण और त्रुटि-प्रकार है।

try 
{ 
    // normal case 
    int result = DoSomething() 
} 
catch (SomethingFailedException ex) 
{ 
    // exceptional case 
} 

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

संपादित करें: एक अपवाद का एक और लाभ यह है कि आप भी जानकारी क्यों कार्रवाई विफल रही प्रदान कर सकता है: उल्लेख करने के लिए भूल। यह जानकारी अपवाद प्रकार, अपवाद के गुण और संदेश पाठ द्वारा प्रदान की जाती है।

+0

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

+0

आपको शायद अपने उदाहरण में 'int' 'मामले में' आउट 'पैरामीटर की आवश्यकता नहीं है; मुझे लगता है कि' आउट 'में दिया गया मान पहले उदाहरण में पैरामीटर दूसरे में वापस किया जाता है। –

+0

@Oren: लेकिन अगर आप त्रुटि कोड के लिए परीक्षण करना भूल जाते हैं, तो संभावित समस्या को नजरअंदाज कर दिया जाता है। अपवाद आपको उच्च स्तर पर समस्या को संभालने की अनुमति देते हैं, उदाहरण के लिए बंद करें खिड़की, लेकिन क्लाइंट या जो कुछ भी नहीं। मैं त्रुटि कोड वाले कोड के साथ काम करता था, और यही वह है जिसे मैं आपदा कहता हूं ... मैं त्रुटियों के बारे में बात कर रहा हूं, न कि "बस-नो-वैल्यू" -सेस के बारे में। –

3

अपवाद क्यों नहीं फेंकें?

+4

अपवादों का उपयोग न करें अगर यह वास्तव में असाधारण नहीं है। – Manu

+1

लेकिन आप नहीं जानते कि यह असाधारण है या नहीं, केवल ओपी करता है। शायद ओपी में झुकना चाहिए; क्या आप सामान्य परिस्थितियों में अपनी विधि को विफल होने की उम्मीद करते हैं? यदि नहीं, तो अपवाद जाने का तरीका है। –

+1

मैं .NET डिज़ाइन दिशानिर्देशों से उद्धरण देता हूं: "अपवाद रिपोर्टिंग त्रुटियों के लिए मानक तंत्र हैं। अनुप्रयोगों और पुस्तकालयों को त्रुटियों को संवाद करने के लिए रिटर्न कोड का उपयोग नहीं करना चाहिए।" http://msdn.microsoft.com/en-us/library/ms229014(VS.80).aspx – Mathias

2

जब तक प्रदर्शन प्राथमिक चिंता का विषय है कि आप एक int लौट सकते हैं और विफलता पर एक अपवाद फेंक देना चाहिए।

1

मैं आउटपुट पैरामीटर का उपयोग करने के पक्ष में हूं। मेरी राय में, यह ऐसी स्थिति है जिसके लिए आउटपुट पैरामीटर का उपयोग सबसे उपयुक्त है।

हाँ, आप यदि और केवल यदि आप एक विकल्प के मूल्य है कि आप अपने कोड के बाकी हिस्सों में उपयोग कर सकते हैं अपने कोड एक एक लाइनर के रूप में रखने के लिए सम्मिलित ऑपरेटर का उपयोग कर सकते हैं। मुझे अक्सर लगता है कि यह मेरे लिए मामला नहीं है, और यदि मैं एक मूल्य पुनर्प्राप्त करने में सफलतापूर्वक सक्षम था, तो मैं एक अलग कोड पथ निष्पादित करना पसंद करूंगा।

 int value; 
     if(DoSomethingWonderful(out value)) 
     { 
      // continue on your merry way 
     } 
     else 
     { 
      // oops 
      Log("Unable to do something wonderful"); 

      if (DoSomethingTerrible(out value)) 
      { 
       // continue on your not-so-merry way 
      } 
      else 
      { 
       GiveUp(); 
      } 
     } 

साथ ही, यदि मूल्य है कि मैं प्राप्त करना चाहते हैं वास्तव में नल, तो एक आउटपुट पैरामीटर और एक बूलियन वापसी मान के साथ एक समारोह का उपयोग कर रहा है, मेरी राय में, सबसे आसान तरीका है के बीच अंतर बताने के लिए "मैं मान को पुनः प्राप्त करने में असफल रहा "और" मैंने जो मूल्य पुनर्प्राप्त किया वह शून्य है "। कभी कभी मैं इस तरह के निम्न उदाहरण में, उस भेद के बारे में परवाह:

private int? _Value; 
    private bool _ValueCanBeUsed = false; 

    public int? Value 
    { 
     get { return this._Value; } 
     set 
     { 
      this._Value = value; 
      this._ValueCanBeUsed = true; 
     } 
    } 

    public bool DoSomethingTerrible(out int? value) 
    { 
     if (this._ValueCanBeUsed) 
     { 
      value = this._Value; 
      // prevent others from using this value until it has been set again 
      this._ValueCanBeUsed = false; 
      return true; 
     } 
     else 
     { 
      value = null; 
      return false; 
     } 
    } 

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

0

दिलचस्प बात यह मेरी निजी राय में काफी विधि की प्रकृति के आधार sways। विशेष रूप से, यदि विधि का उद्देश्य को "कुछ करने" के विरोध में एक मान पुनर्प्राप्त करना है।

पूर्व:

bool GetSerialNumber(out string serialNumber) 

बनाम

string GetSerialNumber() // returns null on failure 

दूसरे किसी भी तरह मेरे लिए लगता है और अधिक "प्राकृतिक", और इसी तरह:

bool GetDeviceId(out int id) 

बनाम

int? GetDeviceId() // returns null on failure` 

लेकिन मैं मानता हूं कि यह वास्तव में "कोडिंग शैली" क्षेत्र में पड़ता है।

ओह, और मैं भी अपवाद फेंकने के पक्ष में जाते हैं:

int GetDeviceId() // throws an exception on read failure 

मैं अभी भी क्यों वे तो गलत होगा पर बेचा नहीं कर रहा हूँ। क्या हम उस पर धागा कर सकते हैं, ओरेन? ;-)

+0

http://stackoverflow.com/questions/1744070/why-should-exceptions-be-used- संयोग से –

0

मैं माइक्रोसॉफ्ट के "कोशिश" पैटर्न को नापसंद करता हूं जिसमें "आउट" पैरामीटर डेटा आइटम को वापस करने के लिए उपयोग किया जाता है। अन्य चीजों के अलावा, उस फैशन में कोडित विधियों को कॉन्वेंट इंटरफेस में इस्तेमाल नहीं किया जा सकता है। मैं एक विधि को कोडित करता हूं: T GetValue(out bool Successful) या शायद T GetValue(out GetValueErrorEnum result); या T GetValue(out GetValueErrorInfo result); यदि किसी सत्य/झूठी से परे कुछ की आवश्यकता हो। चूंकि प्रत्येक डेटा प्रकार में एक कानूनी डिफ़ॉल्ट मान होता है, इसलिए फ़ंक्शन विफल होने पर क्या वापस करना है यह तय करने में कोई समस्या नहीं है। कॉलिंग कोड आसानी से कह सकते हैं:

 
    bool success; 
    var myValue = Thing.GetValue(ref success); 
    if (success) 
    .. do something using myValue 
    else 
    .. ignore myValue 

यह अच्छा होगा अगर .net और सी # मापदंडों सच covariant की पेशकश की 'बाहर नकल' (फोन करने वाले परिणाम के लिए जगह आवंटित होता है, कहा जाता है कार्य करने के लिए है कि अंतरिक्ष के लिए सूचक पारित , और फ़ंक्शन लौटने के बाद केवल आवंटित स्थान को आवंटित चर में कॉपी करें)।

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