Параметры отметить как не допускающий значение null в C#/.Чистая?


есть ли простой атрибут или контракт данных, который я могу назначить параметру функции, который предотвращает null от передачи в C# / .NET? в идеале это также проверит во время компиляции, чтобы убедиться, что литерал null нигде не используется для этого и во время выполнения throw ArgumentNullException.

в настоящее время я пишу что-то вроде ...

if (null == arg)
  throw new ArgumentNullException("arg");

... для каждого аргумента, который я ожидаю, чтобы не быть null.

на той же ноте, есть противоположность Nullable<> в результате чего следующее потерпит неудачу:

NonNullable<string> s = null; // throw some kind of exception
7   79   2008-11-14 23:42:28

7 ответов:

к сожалению, во время компиляции ничего не доступно.

у меня есть немного hacky solution который я недавно опубликовал в своем блоге, который использует новую структуру и преобразования.

в .NET 4.0 с Контракты Кода вещи, жизнь будет намного лучше. По-прежнему было бы неплохо иметь фактический синтаксис языка и поддержку вокруг не-nullability, но контракты кода очень помогут.

у меня также есть метод расширения в MiscUtil называется ThrowIfNull, что делает его немного проще.

один последний пункт-любая причина для использования "if (null == arg)" вместо "if (arg == null)"? Я считаю, что последнее легче читать, и проблема, которую Первый решает в C, не относится к C#.

Я знаю, что это очень старый вопрос, но этот отсутствовал здесь:

Если вы используете ReSharper вы можете использовать Аннотированная База.

Проверьте валидаторы в библиотеке предприятия. Вы можете сделать что-то вроде :

private MyType _someVariable = TenantType.None;
[NotNullValidator(MessageTemplate = "Some Variable can not be empty")]
public MyType SomeVariable {
    get {
        return _someVariable;
    }
    set {
        _someVariable = value;
    }
}

затем в коде, когда вы хотите проверить его:

Microsoft.Practices.EnterpriseLibrary.Validation.Validator myValidator = ValidationFactory.CreateValidator<MyClass>();

ValidationResults vrInfo = InternalValidator.Validate(myObject);

Я знаю, что невероятно опоздал с этим вопросом, но я чувствую, что ответ станет актуальным, поскольку последняя крупная итерация C# приближается к выпуску, а затем выпущена. В C# 8.0 произойдет серьезное изменение, C# будет предполагать все типы считаются не null.

по словам Мадса Торгерсена:

проблема в том, что пустые ссылки очень полезные. В C# они значение по умолчанию для каждого ссылочного типа. Что еще будет по умолчанию ценность будет? Какое еще значение будет иметь переменная, пока вы не сможете решить что еще ставить? Какую еще ценность мы могли бы проложить недавно выделенный массив ссылок закончен, пока вы не доберетесь до заполняешь его?

кроме того, иногда null является разумным значением само по себе. Иногда вы хотите представить тот факт, что, скажем, поле не имеет значение. Что это нормально, чтобы передать "ничего" для параметра. Акцент иногда, правда. И здесь лежит другая часть проблемы: Такие языки, как C# ,не позволяют вам выразить, является ли null прямо здесь a хорошая идея или нет.

Итак, резолюция, изложенная Мэдс, такова:

  1. мы считаем, что чаще всего требуется, чтобы ссылка не была нулевой. Значение null для ссылочных типов было бы более редким видом (хотя у нас нет хороших данных, чтобы сказать нам сколько), поэтому именно они должны требовать новой аннотации.

  2. язык уже имеет понятие-и синтаксис для-nullable типов значений. Аналогия между ними сделала бы язык сложение концептуально проще, а лингвистически проще.

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

пример нужной функции:

public class Person
{
     public string Name { get; set; } // Not Null
     public string? Address { get; set; } // May be Null
}

предварительный просмотр доступен для Visual Studio 2017, 15.5.4 + preview.

не самый красивый, но:

public static bool ContainsNullParameters(object[] methodParams)
{
     return (from o in methodParams where o == null).Count() > 0;
}

вы могли бы получить более творческий подход в методе ContainsNullParameters тоже:

public static bool ContainsNullParameters(Dictionary<string, object> methodParams, out ArgumentNullException containsNullParameters)
       {
            var nullParams = from o in methodParams
                             where o.Value == null
                             select o;

            bool paramsNull = nullParams.Count() > 0;


            if (paramsNull)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var param in nullParams)
                    sb.Append(param.Key + " is null. ");

                containsNullParameters = new ArgumentNullException(sb.ToString());
            }
            else
                containsNullParameters = null;

            return paramsNull;
        }

конечно, вы можете использовать перехватчик или отражение, но они легко следовать / использовать с небольшими накладными расходами

ОК этот ответ немного запоздал, но вот как я его решаю:

public static string Default(this string x)
{
    return x ?? "";
}

используйте этот метод exension, тогда вы можете рассматривать пустую и пустую строку как одно и то же.

например.

if (model.Day.Default() == "")
{
    //.. Do something to handle no Day ..
}

не идеально, я знаю, как вы должны помнить, чтобы позвонить по умолчанию везде, но это одно решение.

public void foo(int? id, string name)
{
    if (id == null)
    {
       throw new ArgumentNullException("id");
    }
    if (name == null)
    {
       throw new ArgumentNullException("name");
    }

    this.foo = id.Value;
    this.fooName = name;
}

там вы идете, в противном случае просто определить другой оператор.