Is it possible to refactor this extension method?

后端 未结 6 788
小鲜肉
小鲜肉 2020-12-24 07:40

I have the following extension method:

public static void ThrowIfArgumentIsNull(this T value, string argument) 
    where T : class
{
    if (value          


        
相关标签:
6条回答
  • 2020-12-24 08:19

    I would recommend that you rather do the following:

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

    Using generics in this case doesn't seem to add any value. But as to your original question, I don't think that's possible.

    0 讨论(0)
  • 2020-12-24 08:24

    I like Enforce from the Lokad Shared Libraries.

    Basic syntax:

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

    This will throw an exception with the parameter name and type if any of the arguments is null.

    0 讨论(0)
  • 2020-12-24 08:31

    See also ArgumentNullException and refactoring for a complete solutions along the same lines as the answer.

    What about:

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

    then define ThrowIfArgumentIsNull as

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

    sorry I don't have the time to fill in the detail or provide the full code at present.

    0 讨论(0)
  • 2020-12-24 08:33

    In a word: no.

    The extension method is passed a value. It has no idea where the value comes from or what identifier the caller may have choosen to refer to it as.

    0 讨论(0)
  • 2020-12-24 08:33

    I find it easiest to do this using a code snippet.

    In your example, I can type tna<tab>qwerty<enter>.

    Here is the snippet:

    <?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>
    
    0 讨论(0)
  • 2020-12-24 08:34

    No, you can't do this. It would be nice, but it's not possible without some sort of AOP getting involved. I'm sure PostSharp can do a nice job, hopefully using attributes, and in Code Contracts it would just be:

    Contract.Requires(qwerty != null);
    

    Ideally I'd like a PostSharp attribute which generates the Code Contracts call - and I'll play around with that at some point - but until then, the extension method you've got is the best approach I've found...

    (If I ever try the PostSharp + Code Contracts approach, I'll certainly blog about it, btw... Mono Cecil might make it reasonably easy too.)

    EDIT: To expand on Laurent's answer, you could potentially have:

    new { qwerty }.CheckNotNull();
    

    And if you had lots of non-nullable parameters, you could have:

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

    This would have to use reflection to work out the properties. There are ways that you could avoid doing the reflection on every access, building a delegate for each property and generally making it whizzy. I may investigate this for a blog post... but it's somewhat icky, and I prefer the idea of being able to just attribute the parameters...

    EDIT: Code implemented, and blog post duly made. Ick, but fun

    0 讨论(0)
提交回复
热议问题