Рассмотрим этот неизменный тип:
public class Settings
{
public string Path { get; private set; }
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(Path != null);
}
public Settings(string path)
{
Contract.Requires(path != null);
Path = path;
}
}
Здесь нужно отметить две вещи:
- Существует инвариант контракта, который гарантирует, что свойство
Path
никогда не может быть null
- Конструктор проверяет значение аргумента
path
на соответствие инварианту предыдущего контракта
На этом этапе экземпляр Setting
никогда не может иметь свойства null
Path
.
Теперь посмотрите на этот тип:
public class Program
{
private readonly string _path;
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(_path != null);
}
public Program(Settings settings)
{
Contract.Requires(settings != null);
_path = settings.Path;
} // <------ "CodeContracts: invariant unproven: _path != null"
}
По сути, он имеет свой собственный инвариант контракта (в поле _path
), который не может быть выполнен во время статической проверки (см. Комментарий выше). Это звучит немного странно для меня, так как это легко доказать:
settings
является неизменным
settings.Path
не может быть нулевым (поскольку в настройках указан соответствующий контрактный инвариант)
- поэтому, присваивая
settings.Path
значение _path
, _path
не может быть нулевым
Я что-то здесь упустил?