在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);
}
}
项目属性 - &gt;构建 - &gt;检查“优化代码”。运行应用程序获得无限循环。 这是正确的行为还是在compiller中的错误?
Upd1: 所以这似乎非常罕见的情况下,未经减少和重新抛出异常。 在Windows 7上的VS 2015中编译时重复(在几台机器上试用)。在Windows 10的VS2015中工作正常 如果更改这样的代码
也可以int i = 3;
do
{
try
{
throw new Exception();
}
catch (Exception) when (--i > 0)
{
Thread.Sleep(10);
}
} while (true);
这将更适合现实世界的例子(因为未展开的堆栈)
答案 0 :(得分:2)
我认为这可能是一个错误。你应该这样报告,IMO。不管是不是,我都不建议你采用这种方法。
首先,您在异常过滤器中有副作用。这通常可能是一种不好的做法。用CQS术语来思考它;过滤器是查询,而不是命令。
其次,你并没有真正获得任何收益。因为你在下一个块中捕获了相同的异常,所以你从异常过滤器行为中获得了什么(如果不匹配则没有堆栈展开)而只是将逻辑放入第二个catch块?什么都没有。
代码:
int i = 3;
do
{
try
{
throw new Exception();
}
catch (Exception)
{
if (--i < 0)
throw;
Thread.Sleep(10);
}
} while (true);
表示您总是希望捕获异常,但是在面对被捕获的异常时,您希望采取不同的行为,具体取决于其他条件。这使得它比异常过滤器更好地表达重试概念,异常过滤器表达了根据其他条件你只想捕获异常的想法。
答案 1 :(得分:0)
快速修复。你可以将你的减量逻辑移到catch中。并将计数器减少1。
public static void Retry()
{
int i = 3 - 1;
do
{
try
{
throw new Exception();
}
catch (Exception) when (i < 0)
{
throw;
}
catch (Exception)
{
i--;
Thread.Sleep(10);
}
} while (true);
}
确定。我现在可以说这是一个bug。测试表明您的代码在32位模式下工作正常。但不适用于64位模式。