2014-10-02 38 views
2

我有以下類:代碼合同靜態檢查器:可能調用空引用的方法 - 爲什麼?

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; 
    } 
} 

請注意,我用Contract.Ensures()以確保構造函數被調用後,FirstSecond永遠不會空。但是,代碼合同在IsSatisfiedBy()方法實施中給我一個警告:CodeContracts: Possibly calling a method on a null reference 'this.First'(與Second相同)。無法弄清楚什麼是錯的,是我還是靜態檢查器?

+0

是否使該字段只讀有所作爲? – 2014-10-02 12:53:17

+2

您可能想要添加一個類不變量,該類不變量指出這些屬性永遠不爲null。 – 2014-10-02 12:54:49

+1

我認爲Contract.Ensures只能確保構造函數調用後屬性First和Second不爲null,而不是方法IsSatisfiedBy。使用不變式似乎是 – Jehof 2014-10-02 12:57:11

回答

0

看來你缺少一些契約和對象不變量。我把你的代碼放在上面,對它進行代碼合同靜態分析,並得到你所得到的。然後,我通過代碼工作,得到滿足靜態分析器的實現。

[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); 
    } 

} 
相關問題