CS1720警告错误地生成了扩展方法。

3
请看下面的程序:
static class Program
{
    static void Extension(this string str)
    {
        if(str == null)
            Console.WriteLine("String is null");
        else
            Console.WriteLine("String is not null");
    }

    static void Main(string[] args)
    {
        default(string).Extension();    // <--- warning
        Extension(default(string));     // <--- no warning
    }
}

输出结果如预期:
String is null
String is null

然而,C#编译器在第一行代码上给出了CS1720警告:

警告CS1720:表达式将始终导致System.NullReferenceException,因为“string”的默认值为null

我的问题是:为什么编译器会建议会出现NullReferenceException? 第一个调用Extension()等同于第二个调用,但第二个不会产生警告。这两个调用都应该是安全的,因为this string str是一个参数,可以安全地为null,如第二行所示。我已经能够在3.5、4.0和4.5编译器上重现这个问题,但在Mono 3.0.7上没有。


2
这只是一个 bug,在此处报告。当时他们似乎并不急于修复它。 - Hans Passant
您可以添加一个#pragma warning disable 1720(并加上一个描述原因的漂亮注释)。 - clcto
2个回答

3
显然,答案是肯定的,这个警告是不正确的。您已经证明了这一点。 (很可能这就是它成为警告的原因)。
正如之前讨论的那样,使用null值调用扩展方法并不会对其造成伤害。 我想编译器团队没有经过所有麻烦来检查要调用的方法是否是扩展方法。

实际上,警告的实现可能早于扩展方法功能。 - Peter Duniho

1
在第一种情况下,您正在取消引用空对象,在第二种情况下,您正在使用 null 参数调用方法。
==更新==
让我重新阐述一下,是的,这似乎不是一个合法的警告。我怀疑编译器发出警告是因为它认为取消引用空对象是“不好的”。该警告可能早于扩展方法功能。
看到 Roslyn 如何分解它会很有趣。

1
这两行代码在功能上是相同的。 - clcto
是的,但我想编译器仍然将其视为空对象的差异。我想Roslyn可能会提供更多信息。 - Dweeberly
没错,这就是问题所在。为什么编译器会将其视为解引用? - clcto
即使是聪明的编译器也不是那么聪明。我怀疑它有一个检查默认(object)的程序,然后跟着一个解引用并发出警告。 - Dweeberly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接