编译器如何在c#中优化异常过滤器?

在C#6中出现异常过滤器.所以我们可以写一些重试逻辑

public static void Retry()
    {
        int i = 3;
        do
        {
            try
            {
                throw new Exception();
            }
            catch (Exception) when (--i < 0)
            {
                throw;
            }
            catch (Exception)
            {
                Thread.Sleep(10);
            }
        } while (true);
    }

在控制台应用程序中它很棒.
但是如果我们用“优化代码”创建网站应用程序,那么将会有无限循环,因为’i’的值永远不会改变.没有“优化代码”,这按预期工作.
如何测试:
在空的asp.net网站应用程序中创建(我尝试.net 4.5.2和.net 4.6).将此代码添加到全局应用程序类

public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        int i = 3;
        do
        {
            try
            {
                throw new Exception();
            }
            catch (Exception) when (--i < 0)
            {
                throw;
            }
            catch (Exception)
            {
                Thread.Sleep(10);
            }
        } while (true);
    }
}

项目属性 – >构建 – >检查“优化代码”.运行应用程序获得无限循环.
这是正确的行为还是在compiller中的错误?

Upd1:
所以这似乎非常罕见的情况下,未经减少和重新抛出异常.
在Windows 7上的VS 2015中编译时重复(在几台机器上试用).在VS2015上的Windows 10工作正常.
如果改变这样的代码也是有效的

int i = 3;
   do
   {
       try
       {
          throw new Exception();
       }
       catch (Exception) when (--i > 0)
       {
          Thread.Sleep(10);
       }
   } while (true);

这将更适合现实世界的例子(因为未展开的堆栈)

最佳答案 我认为这可能是一个错误.你应该这样报告,IMO.不管它是不是我不建议你采取这种方法.

首先,您在异常过滤器中有副作用.这通常是一种不好的做法.用CQS术语来思考它;过滤器是查询,而不是命令.

其次,你没有真正获得任何东西.因为你在下一个块中捕获了相同的异常,所以你从异常过滤器行为中获得了什么(如果不匹配则没有堆栈展开)而只是将逻辑放入第二个catch块?没有.

代码:

int i = 3;
do
{
  try
  {
    throw new Exception();
  }
  catch (Exception)
  {
    if (--i < 0)
      throw;
    Thread.Sleep(10);
  }
} while (true);

表示您总是希望捕获异常,但是您希望在遇到异常时表现不同,具体取决于其他条件.这使得它比异常过滤器更好地表达重试概念,异常过滤器表达了根据其他条件您只想捕获异常的想法.

点赞