2013-02-19 36 views
1

假設下面的代碼來證明財產非空:啓用靜態合同檢查基於一些其他財產

public class CC3 
{ 
    private string _field; 
    private bool _someFlag; 

    public string Property 
    { 
     get { return _field; } 
    } 

    public bool SomeFlag 
    { 
     get { return _someFlag; } 
    } 

    public void SetField() 
    { 
     _field = " foo "; 
     _someFlag = true; 
    } 

    public string Method() 
    { 
     Contract.Requires(SomeFlag); 
     return Property.Trim(); 
    } 
} 

代碼契約的靜態檢查埋怨return聲明Method

可能調用空引用的方法'this.Property'

我需要做些什麼來啓用sta如果SomeFlagtrue,抽取檢查器證明Property永遠不可能是null

+0

不知道是否有關,但也許[工作分配可能會被編譯器重新排序(http://msdn.microsoft。 com/en-us/magazine/jj863136.aspx)導致競爭狀態? – Rawling 2013-02-19 16:55:35

+0

@Rawling:感謝您的評論。我認爲這不相關。無論執行「SetField」主體的順序如何。當調用'Method'時,兩個任務都發生了。 – 2013-02-19 16:56:59

+0

如果一個線程調用'Method'而另一個線程調用'SetField'會怎麼樣? (我不知道這是否被班級以外的事情所排除。) – Rawling 2013-02-19 17:00:49

回答

0

,您可以給靜態分析使用Contract.Assume了援助之手:

public string Method() 
{ 
    Contract.Requires(SomeFlag); 
    Contract.Assume(Property != null); 
    return Property.Trim(); 
} 

或實際在自己的權利增加檢查作爲Contract.Requires。畢竟,僅僅因爲您現在可以手動證明它是真實的,所以當代碼被修改時,您無法保證始終會出現這種情況。事實上,考慮SomeFlag是否真的實際上是一項要求。也許這是一個更清潔的解決方案:

public string Method() 
{ 
    Contract.Requires(Property != null); 
    return Property.Trim(); 
} 
+0

感謝您的建議。我知道這些方法可以讓警告消失。不幸的是,它們不適用於我的代碼。我在這裏發佈的顯然是重現行爲的最低限度。在我的真實代碼中,我有一個方法層次結構,第一個方法包含檢查標誌和一個訪問「Property」的被調用方法。檢查標誌確實是正確的,可以把它看作某種「IsValid」,它檢查的不僅僅是一個屬性不爲null。 – 2013-02-20 06:35:44

+0

關於對類的更改:該參數無效 - 它會使靜態檢查器可以假定的所有內容無效。如果該類被修改,則需要再次運行靜態檢查器。 – 2013-02-20 06:37:52

+0

這正是我的觀點:對類的更改將使靜態檢查器可能假定的所有內容失效。如果你必須通過添加一個'Contract'來幫助檢查者。假設「,那麼每次更改課程時都必須手動檢查該假設是否仍然有效。 – 2013-02-20 07:07:04

0

證明它不是null的唯一方法是證明它不爲null。理想情況下,如果要轉換爲自動屬性,則可以使用不變量。在這個例子中,你可以重寫的財產,以確保null不是一個可能的結果:

public string Property 
{ 
    get { 
     Contract.Ensures(Contract.Result<string>() != null); 
     return _field ?? String.Empty; 
    } 
}