Есть ли способ требовать, чтобы аргумент, предоставленный методу, не был нулевым? - PullRequest
4 голосов
/ 16 апреля 2009

Есть ли лучший способ требовать, чтобы аргумент не был нулевым в методе? Я продолжаю проверять, являются ли какие-либо аргументы, которые требуются моему методу, нулевыми, как показано ниже. Но мне интересно, есть ли лучший способ.

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 ]

1 голос
/ 16 апреля 2009

Это одна из немногих областей, где я думаю, что C # отошел от C ++.

В C ++ вы могли бы написать

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

, чтобы довольно четко указать и компилятору, и другим людям, что foo взял фактический экземпляр Bar. Да, возможно - с усилием - передать foo нулевую ссылку, но это не совсем допустимо в C ++.

Ваше единственное «решение» (своего рода) в C # - вместо этого сделать ваши class es struct s, поскольку типы значений в .NET не могут быть null (в вашем примере, b не может быть null, потому что это System.Int32). Вызов bar() не скомпилируется:

    class A { }
    struct B { }

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

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

Очевидно, что для C # было бы неплохо сделать (намного) более трудным иметь ссылки null; Например, в F # нет обнуляемых типов.

Для некоторых интересных комментариев, связанных с этим вопросом, прочитайте Нулевые ссылки: Ошибка в миллиарде долларов (и комментарии).


Редактировать: Сноска за февраль 2013 года от Эрик Липперт говорит: "... так сложилось, что когда C # был впервые реализован, у него всегда были обнуляемые ссылочные типы, ... кажется правдоподобным, что Nullable<T> мог бы быть реализован для работы с любым типом, и тогда ссылочные типы были бы не обнуляемыми по умолчанию. У нас могла бы быть система типов, где Nullable<string> был единственным допустимым способом представления "строки, которая может быть null ". ..."

1 голос
/ 16 апреля 2009

Мне лично нравится CuttingEdge.Conditions . Он прост в использовании и делает его намного более читабельным.

1 голос
/ 16 апреля 2009

Нет другого лучшего способа. Именно так тонна библиотек Microsoft справляется с ситуацией.

Вы всегда можете использовать метод расширения, чтобы сделать его немного понятнее.

static IsNullArgument(this Object o, string arg)
{
    if (o == null)
        throw ArgumentNullException(arg);
}
0 голосов
/ 15 декабря 2018

Вы можете написать несколько служебных методов. Это общий шаблон в Java.

код пользователя:

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);
}

код реализации:

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;
    }

}

Вы не можете получить имя переменной в исключении. но с помощью трассировки стека и вашего исходного кода можно легко отследить.

0 голосов
/ 16 апреля 2009

Рик Брюстер (автор Paint.NET) написал в блоге об альтернативе Fluent API:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...