Кодовые контракты Vs. Инициализаторы объектов (.net 4.0)

По номиналу, казалось бы, инициализаторы объектов представляют проблему для .NET 4.0 "кодовых контрактов", где обычно инвариант должен быть установлен к тому моменту завершения конструктора объекта. Предположительно, однако, инициализаторы объектов требуют, чтобы свойства были установлены после завершения построения.

Мой вопрос в том, могут ли инварианты "кодовых контрактов" обрабатывать инициализаторы объектов, "как будто" свойства были заданы до завершения конструктора? Это было бы очень приятно!

Ответы

Ответ 1

Ну, я полагаю, что Code Contracts могут вставлять дополнительный вызов инварианту в конце инициализатора объекта - если бы он мог сказать, что это было использовано. (Не забывайте, что в основном использует IL, а не исходный код, насколько мне известно, исходный код используется только для генерации сообщений об ошибках.)

Это поражает меня как плохой дизайн, хотя - воодушевлен неудачной природой инициализаторов объектов. Что бы вы сделали с настройкой свойств после инициализатора объекта? Они могут сделать объект недействительным снова.

Похоже, вы в основном хотите, чтобы хотя бы некоторые свойства были неизменяемыми, но вы хотите получить выгоду от простоты инициализаторов объектов. Именованные аргументы и необязательные параметры в С# 4 дают вам некоторые из них: создайте конструктор со всеми соответствующими свойствами (и значениями по умолчанию), затем вы можете вызвать его следующим образом:

Person person = new Person(firstName: "Jon", lastName: "Skeet");

Это недалеко от синтаксиса инициализатора объекта:

Person person = new Person { FirstName = "Jon", LastName = "Skeet" };

Это не идеально, и я хочу, чтобы у С# была больше поддержки неизменяемых типов (как для создания, так и для использования), но это начало...