C#语法问题 - for循环和行末

4

我目前正在学习C#并阅读一些书籍。我能做一些事情,但只是通过修改示例代码来做到的。我真的感到很沮丧,因为我实际上不理解一些更基本的项目如何/为什么工作。

我刚刚完成了一个控制台应用程序,可以接受参数并逐个显示它们。

代码如下:

using System;

class test
{ static int Main(string[] argsin)
{ 

for (
        int i = 0; 
        i < argsin.Length; 
        i++
    )
Console.WriteLine("Argument: {0}", argsin[i]);
Console.ReadLine();
return -1;
}
}

现在,这个程序完美地工作了。但是,作为一个对Visual Basic有基础(不是双关语!)理解的人来说,它是如何/为什么知道打印正确的参数并继续到下一个而不在第一个Console.WriteLine后退出应用程序呢?我感觉我错过了它是如何工作的基本原理!
接下来,在for循环内部,为什么每行都以分号结束,除了i++
我经常忘记添加它,然后当我尝试弄清楚为什么它无法编译时,我在不该加的地方添加了一个!

@Bobby - 为什么要删除语法标签? - Wil
@Wil:因为我认为[syntax]不是一个非常有用的标签,这只是我的个人观点。我也撤销了我所做的更改,因为我意识到修复格式会删除你问题的整个含义。对此给您带来的不便深感抱歉。 - Bobby
1
这个问题现在完全有意义了。我没有意识到语法已经被编辑过了。虽然我看到我回答它已经太晚了。 :-) - Cody Gray
我认为我们在混淆语法文本格式... - Shadow The Spring Wizard
@Cody Gray,@Shadow Wizard...这是我的愚蠢错误,将for循环跨越多行,但它仍然编译通过,问题无论是在一行还是多行上都是相同的 - 完全关于语法而不是格式。 - Wil
1
@Wil 嗯,C#忽略空格或换行...重要的是各种分号和括号。 - Shadow The Spring Wizard
9个回答

7

您的代码格式有点奇怪,如果按照以下方式重新格式化,我认为它更容易理解:

using System;

class test
{ 
    static int Main(string[] argsin)
    { 
        for (int i = 0; i < argsin.Length; i++)
        {
            Console.WriteLine("Argument: {0}", argsin[i]);  
        }
        Console.ReadLine();
        return -1;
    }
}

从上面的代码可以看出,int i = 0; i < argsin.Length; i++并不是三行不同的代码,它们只是for循环的三个参数。

加上{}让代码更易读,方便看出哪些代码在for循环内执行。


1
为了学习的简单化,我使用的是Notepad++和csc.exe,而不是VisualStudio...谢谢。 - Wil
3
我不确定那是否会使事情更简单——语法高亮和自动格式化在理解正在发生的事情方面非常有用。自动缩进会让你的循环问题更清晰明了! - Dan Puzey
@Wil - 我建议你下载Visual Studio Express,因为它是免费的,并且可以提供语法高亮、格式化、智能感知等功能,以帮助学习类等内容。 - ChrisF
@ChrisF - 我有完整版的VS,这不是问题...和@Dan Puzey - 我理解并喜欢VS,我只是想学习使用单个.cs文件的一些最基本的项目 - 说实话,在这一点上格式化不是问题,只是语法 - 现在我知道for循环会立即处理下一行,这完美地回答了我的问题。 - Wil

4

我将尝试通过与VB语法的比较来解释循环。

在C#中:for (int i = 0; i < 5; i++)

在VB中:For i = 0 To 4

i = 0部分在两者中都相同,因此我想这很清楚 - 这是用于初始化循环迭代器的。

C#中的i < 5部分变成了VB中的0到4....您可以认为这就像VB正在进行“快捷方式”,但在两种情况下的含义是相同的:即循环条件,也就是循环将继续运行的条件,在本例中循环将继续运行,只要i小于5。

最后,C#中需要的i ++部分告诉“每次迭代后迭代器会发生什么?” 在友好的VB中不需要,它会始终默认为将其增加1。

为什么在循环的每个部分后面都要有分号?因为每个部分都有其自己的含义和用途,因此编译器必须知道如何在构建最终代码时分隔这些部分。为什么在i ++部分后面没有分号?同样的原因,您不会在传递给函数的最后一个参数后面加上逗号,例如:Console.WriteLine("Argument: {0}", argsin[i], );

关于循环没有“块”只有一行的情况,在其他答案中已经解释过了,经验法则是C#允许单行块出现而无需括号。


3
按照惯例,C#和所有类C语言在遇到for循环(或if语句等)时会立即运行之后的代码行。个人而言我不喜欢这样编写代码,感觉可读性不足。为了澄清,我们可以添加花括号来表示作用域。
for (
        int i = 0; 
        i < argsin.Length; 
        i++
    )
{
     Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;

现在for循环执行的内容已经明确定义了(如果我们想在循环中做更多事情,可以在花括号之间添加额外的指令)。
编辑: 定义for循环时分号的原因是每个部分都是一个独立的语句。
int i = 0; //creates an integer i and sets its value to 0
i < argsin.Length; sets our comparison operation to define when the loop ends
i++ //what to do at the end in this case increment i by 1

每个需要独立处理,由于分号表示C#语言中语句的结束(这也是每行结尾为分号的原因),我们使用它来分隔语句,以便编译器能够读取它。
虽然2个分号是必需的,但参数并不是必需的,如果需要,我们可以将其更改为以下形式。
int i = 0;
for (;;)
{
     if(i>=argsin.Length){
         break;
     }
     Console.WriteLine("Argument: {0}", argsin[i]);
     i++;
}

这与您编写的方式在功能上是相同的,但我已将所有逻辑从for语句中移出,并将其移到等效位置(或在定义i的情况下移到循环内部)


+1-好的-我也不喜欢那个,但是你解释得很清楚。我会在循环后写括号...现在,对于i++的任何答案,我都会标记为答案吗?(再次说明,这似乎是每个人都在做的事情,但我就是找不到解释!) - Wil
@Wil - 添加了你要求的额外说明。 - Robb
到目前为止,这是最详细的答案了...我看了其他答案,但这一个很可能会被标记为答案! - Wil

2
你的应用程序打印正确数量的参数的原因是 WriteLine 语句是循环的一部分。在 C# 中,如果你在一个 for 语句后只有一行代码,则不需要花括号。(if 语句也是如此)
for (int i = 0; i < argsin.Length; i++)
    Console.WriteLine("Argument: {0}", argsin[i]);

是相同的

for (int i = 0; i < argsin.Length; i++)
{
    Console.WriteLine("Argument: {0}", argsin[i]);
}

关于i++后面的分号,这就是标准写法。通常情况下,for语句都像我在上面的示例中一样写在一行上。
希望这可以帮到你。

第一行写的有点让人困惑,因为应用程序确实可以工作 - 其他所有内容都很棒 - 加1 - Wil
抱歉,打错字了...下次我会更好地校对。谢谢你的点赞。 :) - Jon Mitchell

1

我稍微调整了你的格式,这样你就更容易理解它是如何工作的。

using System;

class test
{
    static int Main(string[] argsin)
    { 

        for (int i = 0; i < argsin.Length; i++ )
            Console.WriteLine("Argument: {0}", argsin[i]);

        Console.ReadLine();
        return -1;
    }
}

对于类C语言有一个特殊的规则:你可以使用if(true) { ... }来定义它的作用域,类似于If True Then ... End If,但如果只有一行代码,你可以决定使用大括号。因此,在iffor[each]后面的下一行将被用作作用域。

i++没有以;结尾,因为它在for的声明中。

另外,不要忘记查看foreach循环。


1
如果我用不同的格式(但语法相同)重写您的方法,可能会使事情更清晰:
static int Main(string[] argsin)
{ 
    for (int i = 0; i < argsin.Length; i++)
    {
        Console.WriteLine("Argument: {0}", argsin[i]);
    }

    Console.ReadLine();
    return -1;
}

请记住,C#不使用换行符来终止语句(与VB不同)。在您的'for'循环中,“第三行”实际上不是“行”,而只是第三个表达式,并由右括号终止。
循环继续而不退出的原因是(没有花括号指示语句块),'for'循环将仅循环紧随循环后面的单个语句 - 也就是'Console.WriteLine'。我猜您认为'ReadLine'和'return'语句将是循环的一部分,但在C#语法中,情况并非如此。(我在我的版本中添加了大括号以使循环范围更清晰)。

1

我来回答你问题的一部分...

for 是一个结构,它有初始化器、循环语句和终止条件。

所以

for (X, Y, Z) { }

将等同于

X;
while (Y)
{
//   code
    Z;
}

关于您的问题,如何不退出应用程序 - for() 将绑定到第一个 NEXT 语句或语句块。在您的情况下,只有一行作为语句。如果有更多行,您应该将它们写在{}中。

1

for循环的典型语法如下:

for( int i = 0; i < argsin.Length; i++ )
{
    //<CODE>
}

所以你可以这样理解它(在你的脑海中):"使用临时值'i'从0开始,当'i'小于'argsin.Length'时,执行'//<CODE>'并将'i'作为值,最后总是以'i++'结束"

一个for循环只需要翻译成:

{
    int i = 0;
    while( i < argsin.Lenth )
    {
        //<CODE>
        i++;
    }
}

(额外的大括号是为了表示当大括号关闭时,'i'超出范围并且不能再使用)。像任何'if'或'while'语句一样,右括号提供了“语句结束”的“字符”(如果您愿意),因此分号是不必要的。之前它们是必须的,因为您必须知道每个语句的结束位置。

[编辑]

顺便说一下:这里还有更多内容需要翻译。有些情况下,您可以包含多个初始化和多个“在每次循环结束时”的指令。在理解了基本概念之后再考虑这些问题。


0

这是for循环的基础,你在循环中声明整数i的起始值为零,并且它应该继续循环直到i等于字符串数组argsin的长度,并在每次迭代中增加i的值。这意味着如果你的argsin数组长度为5,那么循环将会

// first run
for(int i = 0;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[0]);

// second run
for(int i = 1;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[1]);

// third run
for(int i = 2;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[2]);

// forth run
for(int i = 3;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[3]);

// fifth run
for(int i = 4;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[4]);

在运行了5次后,i将变为5,并且不满足5 < 5,退出循环并继续执行下一条语句。

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