Try-Catch-Finally阻止了.NET4.5.1的问题

Mar*_*rkJ 22 c#

我有一个简单的测试代码在.NET3.5中按预期工作,但在使用.NET4.5.1创建的项目中,相同的代码表现完全不同.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            string a = null;
            var x = a.Length;
        }
        catch (Exception ex)
        {
            throw;
        }
        finally
        {
            Console.WriteLine("This is the finally block.");
        }
        Console.WriteLine("You should not be here if an exception occured!");
    }
}
Run Code Online (Sandbox Code Playgroud)

首先,奇怪的是,在运行编译的RELEASE exe文件时,.NET4.5.1中完全忽略了NullReferenceException类型异常.基本上,不会抛出任何错误,但在调试模式下会抛出异常.

第二个(也是最重要的),如果错误与NullReferenceException不同,例如"索引超出范围",则实际上会按预期抛出异常,但是"finally"块永远不会被命中,而不是我期望从try-catch-finally块中获得的行为.我试过不同的机器,我的另外两个同事也在尝试,我们都得到了相同的结果.

似乎我从未真正理解try-catch-finally块,或者.NET4.5.1以不同的方式处理异常,或者.NET4.5.1存在一些错误.我所知道的是上面的代码在.NET3.5中工作,正如我所期望的那样,但是在.NET4.5.1中运行它时似乎没有得到相同的结果.

有人可以对此有所了解吗?我现在完全失去了.

编辑 根据Eric J的回答,我能够解决NullReferenceException问题.自从我提出两个问题后,我将为第二个问题创建一个新线程. Try-Catch-Finally阻止了.NET4.5.1的问题

Eri*_* J. 22

string a = null;
var x = a.Length;
Run Code Online (Sandbox Code Playgroud)

在RELEASE模式下,抖动(只是及时编译器)能够证明x永远不会被引用,因此能够删除赋值.

在DEBUG模式下,抖动不执行该优化.

要强制抛出异常,请执行某些操作x(例如@Henk在评论中建议WriteLine(x)).

编辑

Eric Lippert在评论中指出

......我和任何人一样惊讶于抖动会忽略一个可以抛出的字符串长度指令.这对我来说似乎不对...

抖动优化可能过于激进.

  • 等等,所以编译器会考虑抛出异常*而不是*副作用(很明显,我的意思是给定的代码序列演示了这一点)?要么必须有一些额外的要求(想象其他的后果!)或者这是一个错误. (2认同)