编译器如何在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);
表示您总是希望捕获异常,但是您希望在遇到异常时表现不同,具体取决于其他条件.这使得它比异常过滤器更好地表达重试概念,异常过滤器表达了根据其他条件您只想捕获异常的想法.
标签:c,asp-net,exception-handling,c-6-0 来源: https://codeday.me/bug/20190702/1356925.html