2011-09-15 75 views
3

比方說,我有以下代碼:如何在使用LINQ和ReSharper時擺脫「Possible System.NullReferenceException」警告?

public class Deck { 
    [NotNull IEnumerable<Card> cards = new List<Cards>(); 
    [NotNull] public IEnumerable<Card> Cards { get; private set; } 

    public void AddCard([NotNull] Card card) { cards.Add(card); } 
    ... 
} 

public static IEnumerable<int> CardValuesOfColor(this Deck deck, Color color) 
{ 
    var cards = deck.Cards; 
    return cards.Where(c => c.Color == color).Select(c => c.Value); 
} 

當運行ReSharper的代碼審查,它理所當然地抱怨在「deck.Cards」可能System.NullReferenceException,因爲甲板可以在這個代碼空。這是一件好事,我想保留這一點。

但是,它也會抱怨c.Color和c.Value,因爲它認爲在這些情況下c可能爲null。這看起來過度而且不太有用。

我可以通過將lambda從「c.Color == color」更改爲「c!= null & & c.Color == color」來「修復」c.Color,儘管這對每個Where條款,特別是當我從課堂設計知道該卡片時,卡片不會包含空值。

這並不修復c.Value問題,即使清楚在修改後的「where」子句後,c不可能爲空。

似乎沒有辦法編寫Select(...),OrderBy(...)等子句而不觸發此警告。

當我在我的項目中尋找可能的空引用時,我得到了數百個帶有「問題」的文件。我們廣泛使用LINQ,這些「問題」中的很多但不是全部都是虛假的,但不可能關閉。

我的選擇似乎是關閉可能的空引用檢查或註釋每一次使用LINQ的Select()擴展和評論。這兩者都不適合我。

有沒有第三選擇可以解決這個問題?

+0

我知道一個枚舉可以包含空項目。在這種情況下,我知道它不會通過構建類。我的首選解決方案是有一種告訴ReSharper的方式,所以它會知道。 –

+0

你將如何添加一個空檢查「cards.Select(c => c.Value)」? ReSharper想包裝整個聲明,包括cards.Select()調用自己,在一個if中,這只是簡單的不起作用。 –

+0

Alt +在c(c | .Color)之後立即使用光標輸入上下文動作以生成正確的空檢查 – gorohoroh

回答

0

你必須記住,ReSharper是一個靜態代碼分析工具,即它看起來代碼中的模式,而不考慮代碼的上下文,然後根據什麼建議「改進」或「修復」 ReSharper的某個人(或者你自己,如果你定製了這些設置)被認爲是「更好的」。

靜態分析的問題在於它沒有關於代碼意圖的概念,因此您可以保證它有時會提示實際上會使代碼變得更糟的「改進」,因爲它缺少恰當的上下文代表你的代碼試圖表達的意思。

這與「每個規則都有一個例外」的說法是一樣的,使用像ReSharper這樣的工具的人(像我一樣)不應該盲目地遵循這些建議。

在相關說明:代碼合同將幫助您解決問題