2009-12-09 18 views
27

मैं निम्नलिखित विस्तार विधि है:क्या यह विस्तार विधि रीफैक्टर करना संभव है?

public static void ThrowIfArgumentIsNull<T>(this T value, string argument) 
    where T : class 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException(argument); 
    } 
} 

और इस इसके उपयोग का एक उदाहरण है ....

// Note: I've poorly named the argument, on purpose, for this question. 
public void Save(Category qwerty) 
{ 
    qwerty.ThrowIfArgumentIsNull("qwerty"); 
    .... 
} 

100% ठीक काम करता है।

लेकिन, मुझे यह नहीं लगता कि मुझे अपने अपवाद संदेश की सहायता के लिए चर का नाम कैसे प्रदान करना है।

मैं सोच रहा था अगर यह विस्तार विधि refactor करने के लिए संभव है, तो यह इस तरह कहा जा सकता है ...

qwerty.ThrowIfArgumentIsNull(); 

और यह अपने आप का पता लगा लेता है कि वेरिएबल का नाम 'qwerty' है और इसलिए है ArgumentNullException के मान के रूप में उपयोग करता है।

संभव है? मुझे लगता है कि प्रतिबिंब यह कर सकता है?

+0

यह भी देखें http://stackoverflow.com/questions/869610/c-resolving-a-parameter-name-at-runtime/869629#869629 –

+4

जांचें http://msmvps.com/blogs/jon_skeet/archive/ 2009/12/09/quot-magic-quot-null-argument-testing.aspx - ब्लॉग किया गया :) –

+0

मुझे लगता है कि यह एक बहुत ही साधारण समस्या का एक बहुत ही कठिन समाधान है ... यदि आप विजुअल स्टूडियो का उपयोग कर रहे हैं, तो आप कर सकते हैं इसे बहुत आसान बनाने के लिए कोड स्निपेट का उपयोग करें;) –

उत्तर

34

नहीं, आप यह नहीं कर सकते हैं। यह अच्छा होगा, लेकिन कुछ प्रकार के एओपी शामिल होने के बिना यह संभव नहीं है। मैं PostSharp उम्मीद है कि एक अच्छा काम कर सकते हैं, विशेषताओं का उपयोग यकीन है, और कोड संविदा में यह सिर्फ होगा:

Contract.Requires(qwerty != null); 

आदर्श रूप में मैं एक PostSharp विशेषता है जो उत्पन्न कोड संविदा फोन चाहते हैं - और मैं हूँ इसके साथ कुछ बिंदु पर खेलें - लेकिन तब तक, आपके द्वारा प्राप्त की गई विस्तार विधि सबसे अच्छी पहुंच है ...

(यदि मैंने कभी पोस्टशर्प + कोड अनुबंध दृष्टिकोण का प्रयास किया है, तो मैं निश्चित रूप से इसके बारे में ब्लॉग, बीटीडब्ल्यू ... Mono Cecil इसे भी काफी आसान बना सकता है।)

संपादित करें: लॉरेन के उत्तर पर विस्तार करने के लिए, आप संभावित रूप से प्राप्त कर सकते हैं :

new { qwerty }.CheckNotNull(); 

और अगर आप गैर-व्यर्थ मापदंडों के बहुत था, तो आप हो सकता है:

new { qwerty, uiop, asdfg }.CheckNotNull(); 

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

संपादित करें: कोड लागू किया गया है, और blog post विधिवत बनाया गया है। आईक, लेकिन मजेदार

+0

तत्काल उत्तर के लिए धन्यवाद जॉन :) –

+1

और ब्लॉग पोस्ट के लिए +1 :) मैं लॉर्नेट का जवाब भी देख सकता हूं .... –

+4

मैंने आपके ब्लॉग पोस्ट को पढ़ा है, और आपको ईमानदारी से सभी के माध्यम से जाना नहीं है वह hullabaloo। बस पैरा के बिना 'थ्रोइफनुल()' विधि को कार्यान्वित करें और स्टैक-ट्रेस टूटी डेवलपर को स्टैक को थोड़ा सा पता लगाने दें कि कौन सा तर्क शून्य है। बस एक विचार :) – RCIX

3

एक शब्द में: नहीं।

विस्तार विधि एक मान पास की गई है। यह पता नहीं है कि मूल्य कहां से आता है या कॉलर के पहचानकर्ता ने इसका उल्लेख करने के लिए क्या चुना हो सकता है।

1

मैं सुझाव है कि आप इसके बजाय निम्न कार्य करें:

public static void ThrowIfArgumentIsNull(this object value, string argument) 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException(argument); 
    } 
} 

इस मामले में जेनरिक का उपयोग करते हुए किसी भी मूल्य जोड़ने के लिए प्रतीत नहीं होता। लेकिन आपके मूल प्रश्न के अनुसार, मुझे नहीं लगता कि यह संभव है।

+2

जेनिक्स का उपयोग करने से विधि प्रकार को बाहर करने की विधि मिलती है। ध्यान दें 'जहां टी: कक्षा' – Greg

1

जवाब के रूप में उसी तर्ज पर एक पूरा समाधान के लिए भी ArgumentNullException and refactoring देखें।

के बारे में क्या:

public void Save(Category qwerty) 
{ 
    ThrowIfArgumentIsNull(() => return qwerty); 
    qwerty.ThrowIfArgumentIsNull("qwerty");  
    // .... 
} 

तो के रूप में

public static void ThrowIfArgumentIsNull(Expression<Func<object>> test) 
{ 
    if (test.Compile()() == null) 
    { 
     // take the expression apart to find the name of the argument 
    } 
} 

खेद ThrowIfArgumentIsNull परिभाषित मैं समय विस्तार से भरने या वर्तमान में पूर्ण कोड प्रदान करने के लिए नहीं है।

+0

आपको लैम्ब्डा में' वापसी 'भाग की आवश्यकता नहीं है। –

2

मुझे कोड स्निपेट का उपयोग करके ऐसा करना सबसे आसान लगता है।

आपके उदाहरण में, मैं tna<tab>qwerty<enter> टाइप कर सकता हूं।

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
     <Header> 
       <Title>Check for null arguments</Title> 
       <Shortcut>tna</Shortcut> 
       <Description>Code snippet for throw new ArgumentNullException</Description> 
       <Author>SLaks</Author> 
       <SnippetTypes> 
         <SnippetType>Expansion</SnippetType> 
         <SnippetType>SurroundsWith</SnippetType> 
       </SnippetTypes> 
     </Header> 
     <Snippet> 
       <Declarations> 
         <Literal> 
           <ID>Parameter</ID> 
           <ToolTip>Paremeter to check for null</ToolTip> 
           <Default>value</Default> 
         </Literal> 
       </Declarations> 
       <Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$"); 
     $end$]]> 
       </Code> 
     </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 
1

मैं Lokad Shared Libraries से Enforce चाहते:

यहाँ टुकड़ा है।

बेसिक वाक्य रचना:

Enforce.Arguments(() => controller,() => viewManager,() => workspace); 

यह पैरामीटर नाम और प्रकार के साथ एक अपवाद फेंक देंगे अगर तर्क के किसी भी रिक्त है।

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