在Delphi和C#中,你如何格式化复合语句?

9
作为长期使用Pascal和Delphi的开发人员,我总是这样排列我的开始和结束标记:

begin
  if x = y then
  begin
     ...
     ...
  end
  else
    for i := 0 to 20 do
    begin
      ...
      ...
    end;
end;

让我感到烦恼的是这样格式化的代码:
begin
  if x = y then begin
     ...
     ...
  end
  else
    for i := 0 to 20 do begin
      ...
      ...
    end;
end;

当存在复合语句的几个级别时,我发现这很难阅读。上面的代码还好,因为它不是那么复杂,但为了一致性,我更喜欢所有的开头和结尾都对齐。
当我开始使用c#时,我也会对花括号进行对齐。在C#世界中,什么是正常的做法?
编辑:
有人指出这种问题不应该在SO上提问。我不明白为什么不能。我正在建立一个编码准则文件的过程中。我知道我会遇到某些事情的阻力,我希望在这里得到几个答案,这样我就能准备好迎接这种阻力。

这几乎完全是 Jeff 在 faq 的“我不能在这里提什么样的问题”部分中所描述的那种问题。 - Matt Hamilton
在我看来并没有错。代码格式很重要。 - gabr
我认为只要讨论集中在每种格式的优缺点上,那就没问题。《代码大全》(Jeff最喜欢的书之一)深入探讨了代码格式,所以显然是可以回答的。 - Jim McKeeth
投票关闭。这是一个主观问题的典型范例,人们甚至可能会生气。(对我来说,任何人怎么可能不把他们的“begin”放在新行上仍然是个谜。) - Andreas Rejbrand
@Steve。针对你的编辑,因为SO是一个回答关于编程的技术问题的网站,这些问题有一定的客观性,而不是风格指南,这些指南基本上完全是基于个人意见的。话虽如此,你的问题本身并不是毫无意义的,而且有很多资源可以获取那种信息。 - Mad Physicist
18个回答

6

我个人使用的是:

if Condition then
begin
  DoThis;
end else
begin
  DoThat;
end;

查看Object Pascal Style Guide
在复合if语句中,将每个元素与语句分开放置在新行上。例如:
// INCORRECT
if A < B then begin
  DoSomething; 
  DoSomethingElse;
end else begin
  DoThis;
  DoThat;
end;

// CORRECT
if A < B then 
begin
  DoSomething; 
  DoSomethingElse;
end 
else 
begin
  DoThis;
  DoThat;
end;

以下是一些被认为有效的变体:

以下是一些被认为有效的变体:

// CORRECT
if Condition then
begin
  DoThis;
end else
begin
  DoThat;
end;

// CORRECT
if Condition then
begin
  DoThis;
end
else
  DoSomething;

// CORRECT
if Condition then
begin
  DoThis;
end else
  DoSomething;

也许你会发现这就是为什么我更喜欢上面那个“正确”的,可能是因为我从小就接受了这个指南的影响!实际上,这可能是因为我阅读了很多VCL源代码,它在某种程度上遵循了那个指南! - Steve
1
我已经使用过这两种方法,但是我发现“正确”的例子更易读,一眼就能看清楚。 - Bruce McGee
FTR:我认为它们两个都很丑陋。第一个是因为可读性差,第二个是因为关键字在最左边的列上杂乱无章。我在我的开始/结束块中使用额外的缩进。 - Oliver Giesen
+1. 缩进 Pascal 代码的唯一真正、明智的方法。重要部分(if、else、for、while)都在行首对齐。由于 begin 和 end 在同一行上,插入其他语句很容易。垂直空间不应该是一个问题,特别是现代显示器。如果是这样,你做错了——重构,使用嵌套过程和函数。当我第一次写 Pascal 时,屏幕只有 80*25?我们被教导要将长过程分解为小块(自顶向下设计)。 - Gerry Coll

4

我曾经在Delphi中使用过“悬挂”开头:

if (SomeCondition) then begin
  ...
end;

很奇怪,我并没有用C语言,因为我发现这种方式更易读:

if (SomeCondition)
{
  ...
}

一段时间后,我停止了为了节省一行或两行而牺牲可读性:

if (SomeCondition) then 
begin
  ...
end;

我也会使用显式的开始/结束块,因为我认为这可以提高代码的可读性。我不需要太聪明,只需要能够一眼看出代码的意图即可。更重要的是,任何阅读/维护代码的人都应该能够轻松理解。

if x = y then 
begin
  ...
  ...
end
else
begin
  for i := 0 to 20 do 
  begin
    ...
    ...
  end;
end;

通常情况下,如果明显只有一条语句,我就不会费心去处理。

if (SomeCondition) then
  ...

2

每个人的喜好不同。在我的情况下,我先学习了Modula-2,然后才学习Pascal。Modula-2没有BEGIN关键字,而且每个块都需要一个END。所以代码可能看起来像这样(Modula-2恰好是区分大小写的大写关键字):

IF x = y THEN
    ....
END;

当我开始使用Pascal编码时,这变成了:

if x = y then begin
    ....
end;

以这种方式,代码看起来更像我习惯的样子,同时仍然在可接受的Pascal代码范围内。
对我来说,这些早期印象影响了我在几乎所有其他编程语言中的首选大括号和缩进风格。C#代码没有任何特定的“规范”,就像C或Pascal一样。
唯一真正需要遵循的规则是:在处理现有代码时,请使用已存在的风格;在处理新代码时,请使用您喜欢的风格。

2

我倾向于使用Delphi来完成这个操作:

if a=b then begin
  c;
end else begin
  d;
end;

if x=y then z;

我之所以认为这样更易读是因为它比加上额外换行符更清晰明了。当然,如果我要和其他人一起工作,我会使用我们商定的标准(或者使用当前代码库的标准),但是当我是唯一的工作者时(例如,个人项目),我就会采用这种方式。


我非常喜欢你的第一个语句示例,紧凑的格式和良好的缩进使用使其更易于阅读。关于 "if x=y then z",只有当 z 非常简单时,我才会像这样编写。大多数情况下,我会在下一行缩进后编写 z。 - Martin Liesén
我认为这很难读懂... - Andreas Rejbrand
@mliesen,我非常不同意。我发现那种布局几乎无法阅读。Else和If一样重要,需要在缩进上才能看到。 - Gerry Coll

1

在C语言中的标准是将右括号与起始语句对齐:

if (I am nuts) {
    Psychiatry
}

或者甚至将左大括号放在单独的一行上:

if (I am nuts)
{
    Psychiatry
}

在某些风格中,大括号的缩进方式不同:
if (I am nuts)
  {
    Psychiatry
  }

或者甚至

if (I am nuts)
    {
    Psychiatry
    }

我在Perl中长期使用第一种风格,这是我的else继续的方式:

if (I am nuts) {
    Psychiatry
  } else {
    I am free
}

但是在接触Lisp之后,我发现如果我已经正确缩进,将大括号放在自己的一行上并没有额外的价值:

if (I am completely nuts) {
    Psychiatry }
  else {
    I am free } 

我没有希望用这些想法改变传统的C方式。

另外一件事,Python完全取消了大括号,只依赖缩进,但在我看来,这已经太过分了,因为它会导致像lambda只能有一个语句这样荒谬的事情。


1

我倾向于对齐我的IF和ELSE,并缩进BEGIN/END块。如果我有多个条件的IF语句,我会将其分成多行。如果我发现自己深入了太多,那么我会重新考虑我的编码或将其重构为多个方法。因此,我的代码看起来像下面这样:

if condition1 then
  begin
    // do something
  end
else // not condition1
  begin
    // do something else
  end;

或者更复杂的if条件语句。

if condition1 or
  condition2 or
  condition3 and
  ( condition4 or
    condition5 )
then
  begin
    // do something
  end
else // not conditions
  begin
    // do something else
  end;

0

在大多数情况下,只需让你的IDE为你缩进。


0

个人而言,我更喜欢将连接语句压缩在一行上。例如,在同一行上写出end else可以更清晰地表明下一个语句块与当前语句块相关联。


0

有人发帖说他们会写以下内容:

if x=y then z;

现在我真的不喜欢这个,而且这与美学无关。假设x、y和z是函数,如果我正在逐步执行代码,上述意味着我不能跨越x和y,进入z。

1   if x=y then
2     Z;

我现在可以进入第二行而不必进入第一行。


那将是我,如果它们都是函数并且在Z的开头使用断点没有意义,我同意。然而,在我的代码中,通常情况下不是这种情况(if部分通常是变量),因此我倾向于采用单行方法。 - Michael Madsen
我喜欢保持一致性,即使它们是变量,如果你想在x=y时停在那一行,而不是必须放置条件断点,如果它们位于两行,那么就是一个简单的断点。 - Steve

0

我总是像你的例子一样排列Begin/End。 (除了我会在For语句周围也有一个Begin/End - 以防您稍后添加代码。)

无论如何,如果您的代码有多个层次,则放置Begin/End并不重要,因为它太复杂了。 如果您发现自己超过3个层次,请停止并简化。 创建子程序来清理事情。

《CodeComplete》是关于这种精确事情的最佳参考书。 如果您在阅读该书时没有学到任何东西,那么我就吃我的帽子。


非常同意关于嵌套层数过深的观点!! - Steve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接