2011-09-15 37 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这样的工具的人(像我一样)不应该盲目地遵循这些建议。

在相关说明:代码合同将帮助您解决问题