Кодовые контракты в C # 4.0

#c#-4.0 #code-contracts #design-by-contract

#c #-4.0 #кодовые контракты #разработка по контракту

Вопрос:

Я создал метод, подобный этому

 class PersonCollection
{
  [Contracts.CanReturnNull]  //dont know if something like this exists?
  IPerson GetPerson(Guid personId)
  {
       if (this.persons.Contains(personId))
            return this.persons[personId];
       else
            return null;
  }
}
  

Теперь вызывающий код должен правильно обработать значение null. Есть ли способ выразить контракт для всех вызывающих, который им нужен, чтобы иметь возможность обрабатывать нулевое значение, возвращаемое этим методом?

 PersonCollection pc = new PersonCollection();
IPerson p = pc.GetPerson(anyId);
p.Name = "Hugo";  // here I want to have a curly line
  

Чего я хочу, так это чтобы p был помечен как потенциально проблемный.

РЕДАКТИРОВАТЬ Я просто изменил код и добавил вызывающий код и ожидаемое поведение. Также я добавил атрибут, который, вероятно, не существует в методе GetPerson

Комментарии:

1. В C # переменные ссылочного типа имеют null значение по умолчанию. Если только контракт не GetPerson гарантирует, что IPerson значение не равно null, вызывающий должен учитывать возможность null возврата.

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

Ответ №1:

Code Contract не предоставляет такой функции, как и C#

Кодовые контракты требуют от вызывающего только соблюдения определенных ограничений в начале вызываемого метода. Это так называемые предварительные условия. За постусловия отвечает вызываемый объект и определяет, в каком состоянии будет программа при выходе из вызываемого метода.

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

Комментарии:

1. 1: Кодовые контракты позволяют указывать «этот параметр не может быть нулевым» в качестве предварительного условия или «это возвращаемое значение не будет нулевым» в качестве последующего условия.

Ответ №2:

То, что вы, кажется, хотите (после прочтения комментариев), произойдет по умолчанию:

Если вы включите кодовые контракты в вызывающем коде, верификатор сочтет, что возвращаемое значение GetPerson() может быть нулевым. Итак:

 IPerson GetPerson(Guid personId)
{
   // no pre/post conditions
}

void PrintPerson(IPerson p)
{
   Contract.Requires(p != null);
   ...
}

void Foo()
{
     var p = GetPerson(id);
     PrintPerson(p);    // a warning here: can not verify p != null
}
  

И, что совершенно не имеет отношения к вопросу, обычно это будет более эффективно, если persons — это (например) словарь:

 IPerson GetPerson(Guid personId)
{
   Person p = null;

   this.persons.TryGetValue(personId, out p);
   return p;
}
  

Комментарии:

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

2. @schoet, я понял, суть в том, что вы получаете именно такой результат, ничего не делая. GetPerson() без постусловия уже говорит «Я мог бы вернуть null»

3. > Теперь он работает, я установил версию без статической проверки. Спасибо!