为什么下面的代码行不会创建编译器警告?为什么在一行中抛出2个异常不会生成无法访问的代码警告?
void Main()
{
throw new Exception();
throw new Exception();
}
在我看来,编译器应该告诉你的是,第二抛出异常无法达成。
为什么下面的代码行不会创建编译器警告?为什么在一行中抛出2个异常不会生成无法访问的代码警告?
void Main()
{
throw new Exception();
throw new Exception();
}
在我看来,编译器应该告诉你的是,第二抛出异常无法达成。
这显然是一个编译器错误,它在C#3.0中引入 - 就在我大量重构可达性检查器的时候。这可能是我的不好,对不起。
该错误是完全良性的;基本上,我们只是在警告记者中忘记了一个案例。我们正确地生成可达信息;正如其他人所指出的那样,我们在codegen之前正确修剪了无法访问的代码。
该错误只不过是警告生成器中的一个缺失情况。我们在那里有一些棘手的代码,可以确保当您将大部分代码无法访问时,我们不会报告数十万条警告。编译器具有代码,用于特别报告无条件gotos(“goto”,“break”,“continue”),条件gotos(“if”,“while”等),try-catch-finally try-catch-finally,像锁定和使用),块,返回(yield return和regular return),局部声明,标记语句,开关和表达式语句。
您是否在该列表上看到“throw statements”?我也不。那是因为我们忘了它。
不便之处,敬请原谅。我会向QA发送一条便条,我们将为此修复该语言的未来版本。
感谢您的关注。
感谢Eric的解释。在我们的开发人员意外地重复了“抛出新的Exception()”代码行之后,我只是出于好奇而问,但项目仍然建立(Warnings as Errors on)。 – DaveShaw 2011-06-16 18:50:53
@DaveShaw这个bug有一个奇怪的后果,我在新的“答案”中详细阐述了一下。 – 2012-08-15 19:35:11
它可以给编译器警告/错误,但可悲的是它没有。但是,如果你看IL代码,只有第一个例外被视为。您可以登录到connect.microsoft.com并将其作为您希望看到的内容提出。
如果你ILDASM下面
static void Main(string[] args)
{
Console.Write("Line 1");
throw new Exception();
throw new Exception();
Console.Write("Line 4");
}
的代码,你会得到这个
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 18 (0x12)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Line 1"
IL_0006: call void [mscorlib]System.Console::Write(string)
IL_000b: nop
IL_000c: newobj instance void [mscorlib]System.Exception::.ctor()
IL_0011: throw
} // end of method Program::Main
第一异常对象没有别的转换为IL后。
这个错误(正如Lippert所说的那样)有一些奇怪的后果。当然,这样的代码也没有给出编译时间警告:
static int Main()
{
return 0;
throw new Exception("Can you reach me?");
}
如果你是有创意,你仍然可以使throw
声明诱导(无关)的警告。在这种奇怪的例子中,代码生成,只是因为“绿色”不可达警告:
static int Main()
{
return 0;
throw new Exception(((Func<string>)(() => { if (2 == 2) { return "yellow"; } return "green"; }))());
}
(代码只是从一个lambda创建一个委托实例,并调用委托)。
但是这个例子比较简单,似乎更糟糕:
static int Main()
{
int neverAssigned;
return 0;
throw new Exception(neverAssigned.ToString());
}
这最后的代码示例也没有警告编译!“使用”neverAssigned
没有问题,因为“用法”无法访问。但是你也不会对未被赋值的局部变量(并且永远不会“真正”读取)发出警告。所以重复一遍,根本没有任何警告,这看起来非常错误。
我不知道这种行为是否会在未来版本的Visual C#中改变?改变它会给人们以前没有的警告(在我看来他们应该得到)。
增加:这种行为似乎是不变与Roslyn基础的Visual Studio的2015年
(我注意到,ReSharper的,标志着第二'throw'不可达) – AakashM 2011-06-16 12:56:50
寻呼埃里克利珀的C#编译器6.0 .. – 2011-06-16 13:06:01
@丹Eric Lippert在此之前表示[他不是kibo(在评论中)](http://stackoverflow.com/questions/2508945/can-anyone-explain-this-strange-behaviour) - 通过他与他联系博客,如果你想提醒他有兴趣的问题。 – AakashM 2011-06-16 13:51:00