必须在所有派生类中证明基类属性不变吗?

时间:2010-08-13 09:50:24

标签: code-contracts

我有一个基类,我正在尝试使用Null对象模式来提供默认的记录器实现,然后可以在稍后阶段通过IoC setter注入来更改。

public interface ILog
{
    void Log(string message);
}

public class NoOpLogger: ILog 
{
    public void Log(string message)
    { }
}

public abstract class ClassWithLogger
{
    private ILog _logger = new NoOpLogger();

    protected ClassWithLogger()
    {
        Contract.Assert(Logger != null);
    }

    public ILog Logger
    {
        get { return _logger; }
        set
        {
            Contract.Requires(value != null);
            _logger = value;
            Contract.Assert(Logger != null);
        }
    }

    [ContractInvariantMethod]
    private void ObjectInvariant()
    {
        Contract.Invariant(Logger != null);
    }
}

public sealed class DerivedClass : ClassWithLogger
{
    private readonly string _test;
    public DerivedClass(string test)
    {
        Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(test));
        _test = test;

        // I get warning at end of ctor: "invariant unproven: Logger != null"
    }

    public void SomeMethod()
    {
        Logger.Log("blah");
    }
}

正如我在代码中指出的那样,我的问题是我在派生类的构造函数的末尾发出警告,说明基类中的“Logger!= null”对象不变,即使它很明显也没有被证实什么都没有改变Logger属性值,我也在setter周围有合同,以确保它永远不会为null。

有没有办法避免在所有派生类中重新提出这个事实,或者这仅仅是静态分析器的限制?

更新:最新版本的CodeContracts中已修复问题。此外,我不再需要抽象基类构造函数中的断言(行“Contract.Assert(Logger!= null);”)

1 个答案:

答案 0 :(得分:0)

我刚刚测试了您发布的代码并且工作正常。您使用的是最新版本的Code Contracts(1.4.30707.2)吗?