在C#'for'循环中进行多次初始化

Luk*_*kas 51 c# for-loop initialization

我怎样才能(如果可能的话)在C#for循环中初始化不同类型的多个变量?例:

for (MyClass i = 0, int j = 1; j<3; j++,i++)
Run Code Online (Sandbox Code Playgroud)

Jor*_*ren 85

它无法完成.在循环之前放置一个声明:

MyClass i = 0;
for (int j = 1; j < 3; j++, i++)
Run Code Online (Sandbox Code Playgroud)

或者为了对称性,它们都是:

MyClass i = 0;
int j = 1;
for (; j < 3; j++, i++)
Run Code Online (Sandbox Code Playgroud)

它也可能是其中一个变量比另一个更重要.在这种情况下,将一个变为循环变量可能比较简洁,并且单独处理另一个变量,如下所示:

MyClass i = 0;
for (int j = 0; j < 3; j++)
{
    ...
    i++;
}
Run Code Online (Sandbox Code Playgroud)

注意,如果ij是相同的类型,那么你可以在for循环中声明它们:

for (int i = 0, j = 1; j < 3; j++, i++)
Run Code Online (Sandbox Code Playgroud)

  • 这个答案不再正确。可以使用元组解构来完成:`for ((MyClass i, int j) = (0, 1); j&lt;3; j++, i++)` (9认同)

Fre*_*son 41

当然可以做到.只需使用动态关键字:

public static void Main(string[] args) {
    for (dynamic x = 0, y = new MyClass { a = 20, b = 30 }; x < 100; x++, y.a++, y.b--) {
        Console.Write("X=" + x + " (" + x.GetType() + "\n" +
                      "Y.a=" + y.a + ",Y.b=" + y.b + " (" + y.GetType() + "\n");
     }
}

class MyClass {
    public int a = 0, b = 0;
}
Run Code Online (Sandbox Code Playgroud)

祝你有美好的一天!

  • 史诗但我建议不要使用这个:) (14认同)
  • 除非你想调试运行时异常,否则不要这样做,因为如果你使用`MyClass`的不存在的成员或者使用`x`就像`string`那样静态类型检查器将不会再发出警告.如果你非常担心你的变量仍然在范围内,那就像@Vladimir Liubimov建议[在他的回答中](http://stackoverflow.com/a/36053107/345004)并在一个区块中嵌套你的. (2认同)

Bil*_*l W 15

是的,可以做到.您可以初始化不同类型的变量在for语句,但你不能申报的语句中不同类型的变量.为了在for语句中初始化不同类型的变量,必须在for循环之前声明所有类型.例如:

int xx;
string yy;
for(xx=0, yy=""; xx<10; xx++)
    {
    ....
    }
Run Code Online (Sandbox Code Playgroud)

[编辑]添加更多信息以获得完整性.这超出了OP的要求,但可能对其他人有所帮助.在for循环中初始化相同类型的变量很简单,只需用逗号分隔初始化即可.您还可以在第三部分中更改多个变量.在第二个比较部分中不能有多个逗号分隔的部分,但您可以使用&& || 而且!基于多个变量制作复杂的布尔部分.

for(int i=0, j=0, k=99; i<10 && k<200; i++, j++, k += 2)
Run Code Online (Sandbox Code Playgroud)

但是,制作一个如此复杂的for语句并不难理解正在发生的事情并不是一个好习惯.


Han*_*ant 9

有害吗?

是的,非常如此.语言解析器有两个重要的职责.一个是每个人都熟悉的工作,将文本转换为可执行程序.但非常重要的是它可以检测到无效的程序并为程序员生成有意义的诊断,以便他可以修复他的代码.

在非常基础的层面上,语言解析器区分声明,语句表达式.大括号语言会混淆这种区别,您可以将任何表达式转换为语句,只需在其后面加一个分号即可.在某些情况下,在语句中接受声明,for(;;)语句就是一个很好的例子.最明显的是,这种语法在C或C++语言中是完全可以接受的:

int x = 42;
x;
Run Code Online (Sandbox Code Playgroud)

这不是一件好事,它是无意义的代码.C#语言提高了标准,它将拒绝这一点.但不是:

int x = 42;
x++;
Run Code Online (Sandbox Code Playgroud)

添加到语言分析器的特殊规则接受此规则.

没有任何卷括号语言可以接受的是将声明转换为表达式.那种方式就是疯狂,龙在地图的尽头,船只从边缘掉下来,没有留下好的信息报告.逗号运算符要求左手和右手操作数为表达式.声明不是表达,故事的结尾.


age*_*ega 6

从 C# 7 开始,使用元组:

\n\n
for (var foo = (i:new MyClass(0), j:1); foo.j < 3; foo.i++, foo.j++)) { \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n


Vin*_*ent 6

从 C#7.0 开始,您可以使用解构语法:

for (var (i, j) = (0, (MyClass) 1); j < 3; i++, j++)
{
    Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)

我假设你已经为 MyClass 定义了所有的重载

internal class MyClass
{
    private MyClass(int i)
    {
        Value = i;
    }

    private int Value { get; set; }

    public static explicit operator MyClass(int i) => new MyClass(i);
    public static implicit operator int(MyClass d) => d.Value;

    public static MyClass operator ++(MyClass a)
    {
        a.Value++;
        return a;
    }
}
Run Code Online (Sandbox Code Playgroud)


Vla*_*mov 5

我通常将声明放在循环之前,并使用额外的花括号来限制声明的范围:

{ //limit the scope: i, count, iDivisibleBy2, iDivisibleBy3, iDivisibleBy5
    int i = 0, count = 100;
    bool iDivisibleBy2 = true, iDivisibleBy3 = true, iDivisibleBy5 = true;
    for( ; i < count; ++i, iDivisibleBy2 = (i % 2 == 0), iDivisibleBy3 = ( i % 3 == 0 ), iDivisibleBy5 = ( i % 5 == 0 ) )
    {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)