C# 代码契约静态检查器:可能对空引用调用方法—;为什么?

C# 代码契约静态检查器:可能对空引用调用方法—;为什么?,c#,.net,code-contracts,C#,.net,Code Contracts,我有以下课程: public class AndSpecification<TEntity> : ISpecification<TEntity> { protected ISpecification<TEntity> First { get; private set; } protected ISpecification<TEntity> Second { get; private set; } public bool I

我有以下课程:

public class AndSpecification<TEntity> : ISpecification<TEntity>
{
    protected ISpecification<TEntity> First { get; private set; }
    protected ISpecification<TEntity> Second { get; private set; }

    public bool IsSatisfiedBy(TEntity entity)
    {
        return First.IsSatisfiedBy(entity) && Second.IsSatisfiedBy(entity);
    }

    public AndSpecification(ISpecification<TEntity> first, ISpecification<TEntity> second)
    {
        Contract.Requires(first != null);
        Contract.Requires(second != null);
        Contract.Ensures(First != null);
        Contract.Ensures(Second != null);

        First = first;
        Second = second;
    }
}
公共类和规范:I规范
{
受保护的isspecification First{get;private set;}
受保护的isspecification Second{get;private set;}
公共事业部(TEntity实体)满意
{
返回第一个ISsatifiedby(实体)和第二个ISsatifiedby(实体);
}
公共和规范(I规范第一,I规范第二)
{
Contract.Requires(第一个!=null);
Contract.Requires(第二个!=null);
合同。确保(第一个!=null);
合同。确保(第二个!=空);
第一=第一;
秒=秒;
}
}

注意,我使用
Contract.assures()
来确保调用构造函数后,
First
Second
从不为空。但是,代码契约在issatifiedby()方法实现中给了我一个警告:CodeContracts:可能对空引用调用方法“this.First”(与第二个方法相同)。无法找出问题所在,是我还是静态检查器?

看来您缺少了一些契约和对象不变量。我在上面获取了您的代码,并对其进行了代码契约静态分析,得到了您所得到的结果。然后,我对代码进行了研究,以获得满足静态分析器要求的实现

[ContractClass(typeof(ISpecificationContracts<>))]
public interface ISpecification<TEntity> 
    where TEntity : class
{
    bool IsSatisfiedBy(TEntity entity);
}

[ContractClassFor(typeof(ISpecification<>))]
abstract class ISpecificationContracts<TEntity> 
    : ISpecification<TEntity> where TEntity : class
{
    public bool IsSatisfiedBy(TEntity entity)
    {
        Contract.Requires(entity != null);
        throw new NotImplementedException();
    }
}

public class AndSpecification<TEntity> 
    : ISpecification<TEntity> where TEntity : class
{
    private readonly ISpecification<TEntity> _first;
    private readonly ISpecification<TEntity> _second;

    protected ISpecification<TEntity> First {
        get
        {
            Contract.Ensures(Contract.Result<ISpecification<TEntity>>() != null);
            return _first;
        }
    }
    protected ISpecification<TEntity> Second
    {
        get
        {
            Contract.Ensures(Contract.Result<ISpecification<TEntity>>() != null);
            return _second;
        }
    }

    public bool IsSatisfiedBy(TEntity entity)
    {
        return First.IsSatisfiedBy(entity) && Second.IsSatisfiedBy(entity);
    }

    public AndSpecification(ISpecification<TEntity> first,
                            ISpecification<TEntity> second)
    {
        Contract.Requires(first != null);
        Contract.Requires(second != null);
        Contract.Ensures(_first == first);
        Contract.Ensures(_second == second);

        _first = first;
        _second = second;
    }

    [ContractInvariantMethod]
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", 
        "CA1822:MarkMembersAsStatic", 
        Justification = "Required for code contracts.")]
    private void ObjectInvariant()
    {
        Contract.Invariant(_first != null);
        Contract.Invariant(_second != null);
    }

}
[ContractClass(类型(IsSpecificationContracts))]
公共接口规范
地点:班级
{
bool由TEntity实体提供;
}
[ContractClassFor(typeof(IsSpecification))]
抽象类IsSpecificationContracts
:i规格,其中tenty:class
{
公共事业部(TEntity实体)满意
{
Contract.Requires(实体!=null);
抛出新的NotImplementedException();
}
}
公共类和规范
:i规格,其中tenty:class
{
私有只读i规范优先;
私有只读指定\u秒;
受保护的指定优先{
得到
{
Contract.sure(Contract.Result()!=null);
首先返回;
}
}
受保护的指定秒
{
得到
{
Contract.sure(Contract.Result()!=null);
返回秒;
}
}
公共事业部(TEntity实体)满意
{
返回第一个ISsatifiedby(实体)和第二个ISsatifiedby(实体);
}
公共和规范(首先是规范,
i规格说明(秒)
{
Contract.Requires(第一个!=null);
Contract.Requires(第二个!=null);
合同。确保(_first==first);
保证(秒=秒);
_第一=第一;
_秒=秒;
}
[收缩变量法]
[System.Diagnostics.CodeAnalysis.SuppressMessage(
“Microsoft.Performance”,
“CA1822:MarkMembersAstatic”,
justion=“代码合同所需。”)]
私有无效对象变量()
{
Contract.Invariant(_first!=null);
Contract.Invariant(_second!=null);
}
}

将该字段设置为只读是否会产生影响?您可能希望添加一个类不变量,该类不变量声明属性从不为null。我认为Contract.只确保在构造函数调用后第一个和第二个属性不为null,而不是在方法IsAssifiedBy中。使用不变量似乎是最好的选择way@PeterRitchie不,添加
readonly
支持字段没有帮助。@Damien_The_unsiever@Jehof,谢谢!我认为CodeContracts应该推断出这样一个事实,即
issatifiedby()
方法中的
First
Second
不能为
null
,因为我只在构造函数中设置了它们。