2015-03-21 5 views
7

उदाहरण के लिए, आप आमतौर पर नहीं एक निर्माता में पैरामीटर अशक्त होना चाहता हूँ के लिए जाँच करने के लिए तो यह की तरहसबसे अच्छा तरीका है, अशक्त मानकों (गार्ड क्लाज)

if (someArg == null) 
{ 
    throw new ArgumentNullException(nameof(someArg)); 
} 

if (otherArg == null) 
{ 
    throw new ArgumentNullException(nameof(otherArg)); 
} 

यह करता है कुछ बात को देखने के लिए बहुत सामान्य है थोड़ा सा कोड अव्यवस्थित करें।

क्या इससे बेहतर तर्कों की सूची का तर्क देखने का कोई तरीका है?

कुछ की तरह "तर्कों के सभी की जाँच करें और एक ArgumentNullException फेंक अगर उनमें से किसी रिक्त है और उस तर्क है कि रिक्त थे प्रदान करता है।

वैसे, डुप्लिकेट प्रश्न दावों के बारे में, इस बारे में नहीं है गुणों या अंतर्निहित चीज़ों के साथ तर्कों को चिह्नित करना, लेकिन कुछ लोग इसे कॉल करने के लिए कहते हैं कि गार्ड को प्रारंभिक निर्भरता प्राप्त होती है।

+2

संभवतः डुप्लिकेट [मार्क पैरामीटर सी #/.NET में शून्य नहीं है?] (Http://stackoverflow.com/questions/291340/mark-parameters-as-not-nullable-in-c-net) –

+1

शायद उन्हें ऑब्जेक्ट सरणी में डाल दें और फ़ोरैच लूप का उपयोग करके उन पर फिर से चालू करें? आपको ऐसा कुछ चाहिए? – JoJo

+0

हम आमतौर पर आपके कोड स्निपेट जैसी विधि की शुरुआत में हमारे पैरामीटर की जांच करते हैं। न केवल शून्य के लिए, अन्य व्यावसायिक तर्क व्यवहार के लिए भी। जब तक आपके पास बहुत अधिक पैरामीटर नहीं हैं तब तक मुझे उसमें कोई समस्या नहीं दिखाई दे रही है। कम से कम आप आसानी से अपनी विधि की आवश्यकताओं को पढ़ सकते हैं। – Andre

उत्तर

8
public static class Ensure 
{ 
    /// <summary> 
    /// Ensures that the specified argument is not null. 
    /// </summary> 
    /// <param name="argumentName">Name of the argument.</param> 
    /// <param name="argument">The argument.</param> 
    [DebuggerStepThrough] 
    [ContractAnnotation("halt <= argument:null")]   
    public static void ArgumentNotNull(object argument, [InvokerParameterName] string argumentName) 
    { 
     if (argument == null) 
     { 
      throw new ArgumentNullException(argumentName); 
     } 
    } 
} 

उपयोग:

// C# < 6 
public Constructor([NotNull] object argument) 
{ 
    Ensure.ArgumentNotNull(foo, "foo"); 
    ... 
} 

// C# >= 6 
public Constructor([NotNull] object bar) 
{ 
    Ensure.ArgumentNotNull(bar, nameof(bar)); 
    ... 
} 

DebuggerStepThroughAttribute काफी काम में आता है, ताकि एक excpetion के मामले में, जबकि डिबगिंग (या जब मैं के बाद डीबगर देते हैं अपवाद हुआ) मैं ArgumentNotNull विधि के अंदर समाप्त नहीं होगा बल्कि इसके बजाय कॉलिंग विधि पर जहां शून्य संदर्भ actually खुशी होगी।

मैं ReSharper Contract Annotations का उपयोग कर रहा हूं।

  • ContractAnnotationAttribute यकीन है कि मैं कभी नहीं तर्क ("foo") गलत लिखा है और यह भी स्वचालित रूप से इसे का नाम बदलता है अगर मैं foo प्रतीक का नाम बदलने में आता है।
  • NotNullAttribute कोड विश्लेषण के साथ ReSharper में मदद करता है। तो अगर मैं new Constructor(null) करता हूं तो रीशेर्पर से चेतावनी मिलेगी कि इससे अपवाद होगा।
  • यदि आप सीधे अपने कोड को एनोटेट करना पसंद नहीं करते हैं, तो आप external XML-files के साथ भी वही काम कर सकते हैं जिसे आप अपनी लाइब्रेरी के साथ तैनात कर सकते हैं और उपयोगकर्ता ऑप्टिकल रूप से उनके रीशैपर में संदर्भित कर सकते हैं।
8

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

बॉयलरप्लेट को कम करने के लिए सत्यापन कोड कई लोग इस तरह गार्ड उपयोगिता वर्गों लिखें:

public static class Guard 
{ 
    public static void ThrowIfNull(object argumentValue, string argumentName) 
    { 
     if (argumentValue == null) 
     { 
      throw new ArgumentNullException(argumentName); 
     } 
    } 

    // other validation methods 
} 

(आप अन्य मान्यता तरीकों कि कि गार्ड वर्ग के लिए आवश्यक हो सकता है जोड़ सकते हैं)।

private static void Foo(object obj) 
    { 
     Guard.ThrowIfNull(obj, "obj"); 
    } 
+0

अच्छा! कॉम्पैक्ट और यह ऑपरेटर नाम का भी उपयोग कर सकता है :) धन्यवाद! – SuperJMN

+1

@SuperJMN: आपका स्वागत है :) –

+8

बस एक मामूली नोट, आप तर्क नाम को हार्ड कोडिंग के बजाय 'nameof' ऑपरेटर का भी उपयोग कर सकते हैं, उदा। 'गार्ड। थ्रोइफनुल (ओबीजे, नामोफ (ओबीजे)) ' –

5

अशक्त संदर्भ मुसीबतों आप से बचाव करने के लिए है में से एक प्रकार हैं:

इस प्रकार यह केवल एक पैरामीटर मान्य करने के लिए कोड की एक पंक्ति लेता है। लेकिन, वे एकमात्र नहीं हैं। समस्या उस से व्यापक है, और यह इस पर उबालती है: विधि किसी निश्चित प्रकार के उदाहरण स्वीकार करती है, लेकिन यह सभी मामलों को संभाल नहीं सकती है।

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

अब, हमारे पास शून्य मानों के स्वीकार्य सेट के बाहर एक मान के रूप में शून्य संदर्भ हैं। दूसरी ओर, यह अक्सर होता है कि सेट के कुछ गैर-शून्य तत्व भी अस्वीकार्य (उदा। खाली स्ट्रिंग) हैं।

उस स्थिति में, यह पता चला है कि विधि हस्ताक्षर बहुत व्यापक है, जो तब एक डिजाइन समस्या इंगित करता है। इससे एक नया स्वरूप हो सकता है, उदा। एक उप प्रकार परिभाषित करना, आमतौर पर एक व्युत्पन्न इंटरफ़ेस, जो विधि के डोमेन को प्रतिबंधित करता है और कुछ गार्ड क्लॉज गायब हो जाता है। आप इस लेख में एक उदाहरण देख सकते हैं: Why do We Need Guard Clauses?

1

स्विसनाइफ नामक एक नुजेट पैकेज है। Nuget गैलरी से स्विसknife स्थापित करें। यह आपको Argument.IsNotNullOrEmpty(args,"args")Swissknife.Diagnostics.Contracts नामस्थान के साथ विकल्प idoim के साथ नामांकन के लिए कई विकल्प प्रदान करता है और कई और। आप Option<Class_Name> _someVar सेट कर सकते हैं और फिर _someVar.IsSome or _SomeVar.IsNone यह जांच सकते हैं कि यह शून्य वर्गों के खिलाफ भी मदद करता है। उम्मीद है की यह मदद करेगा।

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