为什么"继续"声明不能在"最终"块内?

lpa*_*oub 106 .net c#

我没有问题; 我只是好奇.想象一下以下场景:

foreach (var foo in list)
{
    try
    {
         //Some code
    }
    catch (Exception)
    {
        //Some more code
    }
    finally
    {
        continue;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将无法编译,因为它引发编译器错误CS0157:

控制不能离开finally子句的主体

为什么?

R. *_*des 150

finally块运行是否抛出异常.如果抛出异常,那该怎么continue办?您无法继续执行循环,因为未捕获的异常会将控制转移到另一个函数.

即使没有抛出异常,finally也会在try/catch块内的其他控制转移语句运行时运行,return例如,它会带来同样的问题.

简而言之,根据finally它的语义,允许将控制从finally块内部转移到块外部是没有意义的.

使用一些替代语义来支持这一点会更有困难而不是有用,因为有一些简单的解决方法可以使预期的行为更清晰.所以你得到一个错误,并被迫正确思考你的问题.这是C#中的一般"把你带入成功的陷阱"的想法.

C#,你,如果成功的话

如果你想忽略异常(通常是一个坏主意)并继续执行循环,请使用catch all块:

foreach ( var in list )
{
    try{
        //some code
    }catch{
        continue;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您只想continue在没有抛出未捕获的异常时,只需将其放在continuetry-block之外.

  • 你能详细说明"把你带入成功的陷阱"的想法吗?我没弄明白:-D (20认同)
  • 这张照片是由Jon Skeet制作的,顺便说一句.我从这里开始:http://msmvps.com/blogs/jon_skeet/archive/2010/09/02/presentation-preparation.aspx (13认同)
  • 我会接受这个作为答案,因为你了解了微软可能决定不接受最终继续的原因.可能图像也说服了我:) (12认同)
  • @Ant http://www.codinghorror.com/blog/2007/08/falling-into-the-pit-of-success.html (9认同)

Mor*_*lus 32

这是一个可靠的来源:

continue语句不能退出finally块(第8.10节).当finally语句在finally块中发生时,continue语句的目标必须在同一个finally块中; 否则,发生编译时错误.

它取自MSDN,8.9.2继续声明.

文件说:

当控制离开try语句时,总是执行finally块的语句.无论控制转移是作为正常执行的结果发生,还是由于执行break,continue,goto或return语句,或者是由于将异常传播出try语句而导致的.如果在执行finally块期间抛出异常,则异常将传播到下一个封闭的try语句.如果另一个异常处于传播过程中,则该异常将丢失.传播异常的过程将在throw语句的描述中进一步讨论(第8.9.5节).

它是从这里8.10的try语句.


Sri*_*vel 31

你可能认为它有意义,但它实际上没有意义.

foreach (var v in List)
{
    try
    {
        //Some code
    }
    catch (Exception)
    {
        //Some more code
        break; or return;
    }
    finally
    {
        continue;
    }
}
Run Code Online (Sandbox Code Playgroud)

当抛出异常时,您打算做什么休息继续?C#编译器团队不希望通过假设break或自己做出决定continue.相反,他们决定抱怨开发者的情况将转移控制模糊不清finally block.

因此,开发人员的工作就是明确说明他打算做什么,而不是编译器假设其他事情.

我希望你明白为什么这不编译!


Chr*_*air 16

正如其他人所说的那样,但专注于例外,它实际上是关于转移控制的模糊处理.

在你的脑海里,你可能会想到这样的场景:

public static object SafeMethod()
{
    foreach(var item in list)
    {
        try
        {
            try
            {
                //do something that won't transfer control outside
            }
            catch
            {
                //catch everything to not throw exceptions
            }
        }
        finally
        {
            if (someCondition)
                //no exception will be thrown, 
                //so theoretically this could work
                continue;
        }
    }

    return someValue;
}
Run Code Online (Sandbox Code Playgroud)

从理论上讲,你可以跟踪控制流程并说,是的,这是"好的".抛出没有异常,没有转移控制.但是C#语言设计师还有其他问题.

抛出异常

public static void Exception()
{
    try
    {
        foreach(var item in list)
        {
            try
            {
                throw new Exception("What now?");
            }
            finally
            {
                continue;
            }
        }
    }
    catch
    {
        //do I get hit?
    }
}
Run Code Online (Sandbox Code Playgroud)

可怕的转到

public static void Goto()
{
    foreach(var item in list)
    {
        try
        {
            goto pigsfly;
        }
        finally
        {
            continue;
        }
    }

    pigsfly:
}
Run Code Online (Sandbox Code Playgroud)

回报

public static object ReturnSomething()
{
    foreach(var item in list)
    {
        try
        {
            return item;
        }
        finally
        {
            continue;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

分手

public static void Break()
{
    foreach(var item in list)
    {
        try
        {
            break;
        }
        finally
        {
            continue;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以在最后,是的,虽然一个轻微使用的可能性,continue在控制不被转移的情况,但一个很好的协议的情况下(多数?)涉及异常或return块.语言设计者认为这样做太模糊,并且(很可能)无法在编译时确保在控制流未被传输的情况下continue使用.


gho*_*ord 11

一般来说continue,在finally块中使用时没有意义.看看这个:

foreach (var item in list)
{
    try
    {
        throw new Exception();
    }
    finally{
        //doesn't make sense as we are after exception
        continue;
    }
}
Run Code Online (Sandbox Code Playgroud)


Hen*_*man 5

"这不会编译,我认为这是完全合理的"

好吧,我认为不是.

当你真正拥有时,你catch(Exception)不需要最终(甚至可能不是continue).

当你有更现实的时候catch(SomeException),如果没有捕到异常会发生什么?你continue想要走一条路,另外一条例外处理.

  • 当你有'赶上'时,我想你可能需要'终于`.它通常用于以可靠的方式关闭资源. (2认同)
  • 我不同意"当你真的有捕获(例外),那么你不需要最终(甚至可能不是继续)." 如果无论是否引发异常,我需要做什么操作怎么办? (2认同)