为什么Try-Catch需要花括号

Shl*_*omo 52 c# try-catch

只是好奇:为什么C#中的try catch语法(Java也?)为多个语句硬编码?为什么语言不允许:

int i;
string s = DateTime.Now.Seconds % 2 == 1 ? "1" : "not 1";
try
   i = int.Parse(s);
catch
   i = 0;
Run Code Online (Sandbox Code Playgroud)

这个例子只是为了琐碎的目的.我知道有int.TryParse.

Mar*_*iss 68

考虑一下这里存在三个(或更多)代码块的事实:

try {}
catch (myexcption)
{}
catch (myotherexception)
{}
finally
{}
Run Code Online (Sandbox Code Playgroud)

请记住,这些都在更大的上下文范围内,未捕获的异常会在堆栈中进一步发挥作用.

请注意,这与具有{}结构的类构造基本相同.

比如说你可能有:

try
try
if (iAmnotsane)
beatMe(please);
catch (Exception myexception)
catch (myotherexception)
logerror("howdy")
finally
Run Code Online (Sandbox Code Playgroud)

现在第二次尝试属于第一次或第二次尝试吗?最后怎么样?所以你看到可选/多个部分符合要求.

  • IF-ELSE是不同的,因为在IF-ELSE中最多只有一个ELSE,而在TRY-CATCH中有0个或更多个CATCH. (16认同)
  • +1用于提供不可读的代码:)尽管如此,嵌套的IF-ELSE块具有相同的问题. (12认同)
  • @ user93422:我不同意.如果不需要大括号,则可能会设计解析以使所有连续捕获属于同一范围.当这不是意图时,这可能会迫使人们使用大括号,但这同样适用于`if(b)if(c)DDD(); 否则EEE();`如果你希望`EEE`在b为假时执行. (3认同)
  • @Shlomo:完全有可能设计出一种语法,可以明确地处理这种情况. (3认同)

Eri*_*ert 50

更新:这个问题是我的博客2012年12月4日的主题.博客上有许多你可能也感兴趣的富有洞察力的评论.感谢您提出的好问题!


正如其他人所指出的那样,所提出的特征引入了令人困惑的模糊性.我有兴趣看看是否有任何其他理由决定不支持该功能,所以我检查了语言设计说明存档.

我在语言设计说明档案中看不出任何可以证明这一决定的理由.据我所知,C#就是这样做的,因为这是其他具有类似语法的语言的做法,并且由于模糊性问题,他们就是这样做的.

我确实学到了一些有趣的东西.在C#的初始设计中,没有try-catch-finally!如果你想尝试使用catch和a finally,那么你必须写:

try
{
  try
  {
      XYZ();
  }
  catch(whatever)
  {
     DEF();
  }
}
finally
{
  ABC();
}
Run Code Online (Sandbox Code Playgroud)

毫不奇怪,这正是编译器分析try-catch-finally的原因; 它只是在最初的分析中将它分解为try-catch内部的try-catch,并假装这首先是你所说的.

  • "所以我检查了语言设计说明档案"......为什么我想象你进入了蝙蝠洞?只有在SO上才能得到这样的答案.你摇滚,埃里克. (22认同)

kid*_*jan 8

或多或少,这是一个关于悬挂其他问题的游戏.

例如,

if( blah )
    if ( more blah )
        // do some blah
else
    // no blah I suppose
Run Code Online (Sandbox Code Playgroud)

没有花括号,else是不明确的,因为你不知道它是否与第一个或第二个if语句相关联.因此,您必须回避编译器约定(例如,在Pascal或C中,编译器假定悬挂的else与最接近的if语句相关联)以解决歧义,或者如果您不希望允许这种歧义,则完全无法编译首先.

同样的,

try
    try
        // some code that throws!
catch(some blah)
    // which try block are we catching???
catch(more blah )
    // not so sure...
finally
    // totally unclear what try this is associated with.
Run Code Online (Sandbox Code Playgroud)

您可以使用约定解决它,其中catch块始终与最接近的try相关联,但我发现此解决方案通常允许程序员编写具有潜在危险的代码.例如,在C中,这个:

if( blah )
    if( more blah )
        x = blah;
    else
        x = blahblah;
Run Code Online (Sandbox Code Playgroud)

...是编译器如何解释这个if/if/else块.然而,搞砸你的缩进和写作也是完全合法的:

if( blah )
    if( more blah )
        x = blah;
else
    x = blahblah;
Run Code Online (Sandbox Code Playgroud)

...现在使得它看起来像else与外部if语句相关联,而实际上由于C约定它与内部if语句相关联.因此,我认为要求括号在解决模糊性和防止相当偷偷摸摸的错误方面有很长的路要走(即使在代码检查期间,这些问题也很容易被忽略).像python这样的语言没有这个问题,因为缩进和空白很重要.


Pat*_*ahy 8

如果你假设C#的设计者只是选择使用与C++相同的语法,那么问题就变成了为什么单个语句需要使用大括号来尝试和捕获C++中的块.简单的答案是Bjarne Stroustrup认为语法更容易解释.

C++的设计和演变中 Stroustrup写道:

"try关键字是完全冗余的,{}括号也是如此,除非在try-block或handler中实际使用了多个语句."

他继续举例说明不需要try关键字和{}.然后他写道:

"但是,我发现这很难解释为了节省支持人员从困惑的用户那里引入冗余."

参考文献:Stroustrup,Bjarne(1994).C++的设计与演变.Addison-Wesley出版社.