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
,因为我只在构造函数中设置了它们。