Is there a way to require that an argument provide

2020-06-18 03:36发布

Is there a better way to require that an argument is not null in a method? I keep checking if any of the arguments that my method requires are null, as show below. But I'm wondering if there is a better way.

public void MyMethod(string a, int b)
{
   if(a==null){throw new ArgumentNullException("a");}
   if(b==null){throw new ArgumentNullException("b");}

   //more stuff here
}

5条回答
混吃等死
2楼-- · 2020-06-18 03:44

There is no other better way. This is the way a ton of Microsoft libraries handle the situation.

You can always use an extension method to make it a little clearer.

static IsNullArgument(this Object o, string arg)
{
    if (o == null)
        throw ArgumentNullException(arg);
}
查看更多
Emotional °昔
3楼-- · 2020-06-18 04:01

I personally like CuttingEdge.Conditions. It's easy to use, and makes this much more readable.

查看更多
够拽才男人
4楼-- · 2020-06-18 04:02

Rick Brewster (author of Paint.NET) blogged about a Fluent API alternative:

http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/

查看更多
Bombasti
5楼-- · 2020-06-18 04:04

You can write some utility methods. This is the common pattern in java.

user code:

public void MyMethod(string a, int b)
{
    //validate each
    Objects.RequireNotNull(a);
    Objects.RequireNotNull(b);

    //or validate in single line as array 
    Objects.RequireNotNullArray(a, b);
}

implementation code:

public static class Objects
{
    public static T RequireNotNull<T>(T arg)
    {
        if(arg == null)
        {
            throw new ArgumentNullException();
        }
        return arg;
    }

    public static object[] RequireNotNullArray(params object[] args)
    {
        return RequireNotNullArray<object>(args);
    }

    public static T[] RequireNotNullArray<T>(params T[] args)
    {
        Objects.RequireNotNull(args);
        for(int i=0; i<args.Length; i++)
        {
            T arg = args[i];
            if(arg == null)
            {
                throw new ArgumentNullException($"null entry at position:{i}");
            }
        }
        return args;
    }

}

You cannot get the variable name in the exception. but with the stack trace and your source code, it should be possible to easily track down.

查看更多
冷血范
6楼-- · 2020-06-18 04:10

This is one of the few areas where I think C# went backwards from C++.

In C++, you could write

void foo(Bar& bar) { /*...*/ }

to quite clearly indicate to both the compiler and other humans that foo took an actual instance of Bar. Yes, it is possible--with effort--to pass foo a null reference but that's not really legal C++.

Your only "solution" (of sorts) in C# is to make your classes structs instead, as value types in .NET can't be null (in your example, b can't ever be null because it is a System.Int32). The call to bar() will not compile:

    class A { }
    struct B { }

    static void foo(A a) { }
    static void bar(B b) { }

    static void Main(string[] args)
    {
        foo(null);
        bar(null);
    }

It certainly seems like it would have been nice for C# to have made it (much) more difficult to have null references; F#, for example, has no nullable types.

For some interesting commentary related to this matter, read Null References: The Billion Dollar Mistake (and the comments).


Edit: A February 2013 footnote from Eric Lippert says "... it just so happened that when C# was first implemented it had always-nullable reference types, ... it seems plausible that Nullable<T> could have been implemented to work on any type, and reference types would then be non-nullable by default. We could have a type system where Nullable<string> was the only legal way to represent "a string that can be null". ... "

查看更多
登录 后发表回答