Этот пример в вики реализует инварианты с JML, который является очень специфическим, экзотические и, возможно, хорошо но это вовсе не обязательно. Также не просто говорить об инвариантах, а просто говорить об утверждении мутатора, делало то, что ожидалось, чего я не думаю о том, когда я думаю об инвариантах. Я не читал Coders at Work, но я сомневаюсь, что кто-то из Coders at Work использовал JML.
В любом случае, я всегда считал, что инварианты - отличный способ «свернуть раньше» и не дать вашему коду пытаться делать разумные вещи, когда на самом деле состояние программы находится в необоснованном (незапланированном) состоянии.
Хорошим примером инварианта в коде C# может быть никогда не давать объект N-Hibernate для сохранения, если этот объект не передал его инварианты, которого должно быть много, чтобы предотвратить нечувствительные данные из входя в базу данных. Давайте посмотрим, если я могу думать о каких-либо других примеров ...
Предположим, у вас есть класс пользователя, который всегда должен иметь электронный адрес свойства первичной, то инвариант для проверки перед сохранением может быть сделать уверен, что поле адреса электронной почты не пустое. В противном случае другая прикладная логика по дороге, которая предполагает адреса электронной почты существуют для всех пользователи могут испортить при попытке отправить пользователю электронное письмо позже.
Предположим далее, что объект User «имеет много» объекты электронной почты, и пусть , что он не имеет никакого смысла для Email существовать без владеющему пользователя, то инвариант на классе Email может быть, чтобы ссылка электронной почты на , ее пользователь всегда не имеет значения null, в противном случае у вас есть объект-сирота, который может привести к ошибкам нулевого указателя при попытке обратиться к владельцу электронной почты.
Предположим, что вы пишете графический интерфейс, который предполагается представить статус объекта Amazon S3 в обычном WPF форме. Инвариантом в форме может быть удостовериться, что форма должным образом связана с ее объектом перед выполнением любых обработчиков событий на этой форме.
Предположим, вы пишете StackOverflow. Инвариантом здесь может быть, чтобы уровень репутации пользователя никогда не был отрицательным, даже , если пользователь принимает штрафные санкции за репутацию. Отрицательная репутация может сломать те симпатичные графики, которые визуализируют как функцию времени (если эти графики не подготовлены , чтобы начертить строки ниже 0-й оси, что они очень может быть ...).
Что касается того, когда проверять инварианты, вы можете сделать это в конце любого метода, который мутирует состояние данных. При наиболее агрессивном и параноидальном уровне защитного программирования вы можете проверить инвариант до и после всех методов.
Свое смешное вы говорите. Инвариантность .NET не связана с другими видами инвариантности. Я не согласен, но, возможно, именно там я ошибаюсь. Возможно, инвариантность типа не связана с классовой инвариантностью и использованием единичного теста или связана только на начальном уровне. Если мы определим «инвариантность», как просто «не изменится». Вопрос: «Как вы проверяете вещи, которые не меняются». Или возникает вопрос: «Как вы проверяете диапазон допустимых значений»? –
@ P.Brian Существует множество типов инвариантов. И дисперсия типа полностью не связана с классовыми инвариантами. Я добавил вступительный параграф. – CodesInChaos
@ P.Brian Чтобы узнать, как принудительно применять инвариант класса в .net 4, см. Ответ «Ли». Если вы это сделаете (и выберите правильные параметры компилятора), ваш код будет переписан, чтобы он тестировал инвариант в конце любого общедоступного метода. – CodesInChaos