C#中的分号

时间:2009-03-07 14:55:25

标签: c#

为什么C#中每一行末尾都需要分号? 为什么编译器不能知道每一行的结束位置?

12 个答案:

答案 0 :(得分:40)

行终止符将使您能够跨多行断开语句。

另一方面,像VB这样的语言有一个行继续符。我个人认为使用分号终止语句而不是继续使用下划线更清晰。

答案 1 :(得分:14)

不,编译器不知道换行是用于语句终止,也不应该。如果您愿意,它允许您将语句带到多行。

请参阅:

string sql = @"SELECT foo
               FROM bar
               WHERE baz=42";

或者大方法重载怎么样:

CallMyMethod(thisIsSomethingForArgument1,
             thisIsSomethingForArgument2,
             thisIsSomethingForArgument2,
             thisIsSomethingForArgument3,
             thisIsSomethingForArgument4,
             thisIsSomethingForArgument5,
             thisIsSomethingForArgument6);

反之,分号也允许多语句行:

string s = ""; int i = 0;

答案 2 :(得分:12)

这是多少陈述?

for (int i = 0; i < 100; i++) // <--- should there be a semi-colon here?
Console.WriteLine("foo")

需要使用分号来消除歧义。

答案 3 :(得分:7)

除了内部标识符和关键字之外,空格并不重要。

答案 4 :(得分:4)

严格地说,这是真的:如果一个人能够找出一个语句结束的地方,那么编译器也是如此。这还没有真正流行起来,很少有语言实现这种类型的任何东西。下一版本的VB可能是第一种实现正确处理语句的语言,它既不需要显式终止也不需要行继续[source]。这将允许这样的代码:

Dim a = OneVeryLongExpression +
        AnotherLongExpression
Dim b = 2 * a

让我们的手指交叉。

另一方面,这个 使解析变得更加困难,并且可能导致错误消息(参见Haskell)。

也就是说,C#使用类似C语法的原因可能是由于营销原因而不是其他任何原因:人们已经熟悉C,C ++和Java等语言。无需引入另一种语法。这有多种原因,但它显然从这些语言中继承了许多弱点。

答案 5 :(得分:4)

我个人同意将一个独特的角色作为行终止符。它使编译器更容易弄清楚你想要做什么。

与流行的看法相反,100%的时间让编译器找不到一个语句结束而另一个语句没有帮助就开始了!有些边缘情况是模糊的,无论是单个语句还是跨越多行的多个语句。

阅读Visual Basic技术主管Paul Vick的this article,了解为什么它不像听起来那么简单。

答案 6 :(得分:3)

分号的另一个好理由是隔离语法错误。当出现语法错误时,分号允许编译器返回正轨,以便类似

a = b + c = d

可以消除歧义

a = b + c; = d

第二个语句中的错误或

a = b + ; c = d

第一个语句中的错误。如果没有分号,则无法说明语句在出现语法错误时的结束位置。缺少括号可能意味着程序的整个后半部分可能被视为一个巨大的语法错误,而不是逐行检查语法。

它还有助于另一种方式 - 如果你打算写

a = b; c = d;

但是错误并且遗漏了“c”然后没有半成品它看起来像

a = b = d

这是有效的,你有一个运行程序,有一个坏的和难以找到的bug,所以分号通常可以帮助捕获错误,否则看起来像有效的语法。另外,我同意每个人的可读性。我不喜欢在没有某种语句终止符的情况下使用语言。

答案 7 :(得分:1)

我一直在考虑这个问题,如果我可以猜测一下语言设计师的动机:

C#显然有分号,因为它来自C的遗产。我最近一直在重读K&amp; R书,很明显Dennis Ritchie真的不想强迫程序员以他认为最好的方式编写代码。这本书充满了各种评论,“尽管我们对这个问题没有教条,但似乎goto语句似乎很少使用,如果有的话”,在关于函数的部分,他们提到他们选择了许多格式样式中的一种,你挑选哪一个并不重要,只要保持一致。

因此,使用显式语句终止符允许程序员根据需要格式化他们的代码。无论好坏,它似乎与C最初设计的方式一致:按照自己的方式行事。

答案 8 :(得分:1)

可以做到。你所指的是“分号插入”。 JavaScript取得了很大的成功,它未在C#中应用的原因取决于它的设计者。也许他们不了解它,或者担心它可能会引起程序员之间的混淆。

有关JavaScript中分号插入的详细信息,请参阅指定JavaScript的ECMA-script standard 262

我引用第22页(PDF格式,第34页):

  
      
  • 当从左侧解析程序时   到右边,输入结束   遇到令牌流   解析器无法解析   输入令牌流作为单个完整   ECMA脚本程序,   然后一个分号是自动插入的   输入流的结束。

  •   
  • 当,如   程序从左到右解析,   遇到一个令牌   一些生产所允许的   语法,但是   生产是限制生产,令牌将是   终端的第一个令牌或   紧随其后的非终结者   注释“[没有LineTerminator   在这里]“在限制生产中(并且有这样的标记是   称为限制令牌)和   限制令牌与他分开   先前的标记至少有一个   LineTerminator,然后是   分号在受限制的令牌之前自动插入。

  •   
     

然而,还有一个额外的   对前面的压倒一切的条件   规则:分号永远不会   如果自动插入   然后将分号解析为空语句   或者如果那个分号   将成为for语句标题中的两个分号之一   (第12.6.3节)。

     

[...]

规范文档甚至包含示例!

答案 9 :(得分:1)

我想说在每个语句之后必须使用分号的最大原因是熟悉C,C ++和/或Java的程序员的熟悉程度。 C#从这些语言继承了许多语法选择,而不是简单地命名它们。以分号结尾的语句只是从这些语言中借用的众多语法选择之一。

答案 10 :(得分:0)

你可以准确地说,要求分号来终止一个语句是多余的。从技术上讲,可以从C#语言中删除分号,但仍然可以使用分号。问题在于它为人类的误解留下了空间。我认为分号的必要性是为人类而不是编译器消除歧义。如果没有某种形式的陈述划界,那么人类就更难以解释这样的构思:

int i = someFlag ? 12 : 5 int j = i + 3

编译器应该能够处理这个问题,但对于人类来说,下面看起来好多了

int i = someFlag ? 12 : 5; int j = i + 3;

答案 11 :(得分:0)

半冒号是C语言的残余,当程序员经常想通过在一行上组合语句来节省空间时。即。

int i; for( i = 0; i < 10; i++ ) printf("hello world.\n"); printf("%d instance.\n", i);

它还帮助编译器,它不够智能,只能简单地推断语句的结束。几乎在所有情况下,出于可读性原因,大多数c#开发人员都不赞同在一行上组合语句。以上内容通常是这样写的:

int i;
for( i = 0; i < 10; i++ )
{
    printf("hello world.\n);
    printf("%d instance.\n", i);
}

非常详细!对于现代语言,可以轻松开发编译器以推断语句结束。 C#可以改成另一种语言,除了空格和缩进标签之外不使用不必要的分隔符,即

int i
for i=0 i<10 i++
   printf "hello world.\n"
   printf "%d instance.\n" i

这肯定会节省一些打字,看起来更整洁。如果使用缩进而不是空格,则代码变得更具可读性。如果我们允许推断类型,我们可以做得更好,并且为了读取([值] = [初始值]到[最终值:

的特殊情况)
for i=1 to 10  // i is inferred to be an integer
    printf "hello world.\n"
    printf "%d instance.\n" i

现在,它开始看起来像f#和f#,在某些方面,几乎就像c#没有不必要的标点符号。但是f#缺少这么多附加功能(比如特殊的.NET语言结构,代码完成和良好的智能感知)。所以,最后f#可以比c#或VB.NET更多的工作来实现,遗憾的是。

就个人而言,我的工作需要VB.NET,我更乐意不用处理分号。 C#是一种过时的语言。 Linq允许我减少我必须编写的代码行数。不过,如果我有时间,我会编写一个c#的版本,它具有f#的许多功能。