Как я могу показать, что метод никогда не вернет ноль (дизайн по контракту) в C # - PullRequest
9 голосов
/ 27 января 2009

У меня есть метод, который никогда не возвращает нулевой объект. Я хочу прояснить, чтобы пользователям моего API не приходилось писать код, подобный этому:

if(Getxyz() != null)
{
  // do stuff
}

Как мне показать это намерение?

Ответы [ 9 ]

10 голосов
/ 27 января 2009

К сожалению, нет никакого способа встроиться в C #

Вы можете задокументировать этот факт, но он не будет автоматически проверен.

Если вы используете resharper, то его можно настроить для правильной проверки, когда метод помечен атрибутом [NotNull].

В противном случае вы можете использовать библиотеку Microsoft Contracts и добавить в метод что-то похожее на следующее, но это довольно много лишних слов для такой простой аннотации.

Contract.Ensures(Contract.Result<string>() != null)

Spec # решил эту проблему, разрешив! после типа, чтобы пометить его как ненулевой тип, например

string! foo

но Spec # может использоваться только для таргетинга на .NET2 и был узурпирован библиотекой Code Contracts.

6 голосов
/ 27 января 2009

Если вы не используете тип, основанный на System.ValueType, я думаю, вам не повезло. Вероятно, лучше всего это четко задокументировать в комментарии XML / метаданных для функции.

2 голосов
/ 27 января 2009

Единственный проверенный тип способ убедиться, что объект C # никогда не возвращает null, - это использовать структуру. Структуры могут иметь члены, которые содержат нулевые значения, но сами по себе никогда не могут быть нулевыми.

Все остальные объекты C # могут быть нулевыми.

Пример кода:

public struct StructExample
{
    public string Val;
}

public class MyClass
{
    private StructExamle example;

    public MyClass()
    {
        example = null; // will give you a 'Cannot convert to null error
    }

    public StructExample GetXyz()
    {
        return null; // also gives the same error
    }
}

Приведенный выше пример не скомпилируется. Если использование структуры приемлемо (она становится типом значения, передается по стеку, не может быть разделена на подклассы), тогда это может работать для вас.

2 голосов
/ 27 января 2009

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

1 голос
/ 27 января 2009

Мне нравится думать об этом с другой стороны: если моя функция может вернуть нулевое значение, мне лучше убедиться, что пользователь функции знает об этом.

0 голосов
/ 27 января 2009

Документируйте и предоставьте исходный код.

0 голосов
/ 27 января 2009

Вы можете включить метод Debug.Assert (). Хотя это, безусловно, не приведет к выполнению условия, оно должно дать понять (вместе с документацией), что нулевое значение недопустимо.

0 голосов
/ 27 января 2009

Либо хорошо документируйте (возможно, с помощью стандартной системы документации .NET), либо вам нужно использовать контрактный API. Вот некоторые: http://geekswithblogs.net/Podwysocki/archive/2008/01/22/118770.aspx http://www.codeproject.com/KB/cs/designbycontract.aspx

0 голосов
/ 27 января 2009

Если у ваших пользователей есть исходный код, использующий стандартный дизайн по контракту API, например: http://www.codeproject.com/KB/cs/designbycontract.aspx может прояснить ситуацию.

В противном случае ваш лучший выбор - через документацию.

...