C#'for'循环中的多次初始化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1658557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple initialization in C# 'for' loop
提问by Lukas
How can I (if it is possible at all) initialize multiple variables of different type in a C# for
loop? Example:
我如何(如果可能的话)在 C#for
循环中初始化多个不同类型的变量?例子:
for (MyClass i = 0, int j = 1; j<3; j++,i++)
采纳答案by Joren
It can't be done. Put one of the declarations before the loop:
做不到。将声明之一放在循环之前:
MyClass i = 0;
for (int j = 1; j < 3; j++, i++)
Or for symmetry, both of them:
或者为了对称,他们两个:
MyClass i = 0;
int j = 1;
for (; j < 3; j++, i++)
It's also possible that one of the variables is more primary than the other. In that case it might be neater to have one be the loop variable, and deal with the other seperately, like this:
也有可能其中一个变量比另一个更重要。在这种情况下,将一个作为循环变量并单独处理另一个可能会更简洁,如下所示:
MyClass i = 0;
for (int j = 0; j < 3; j++)
{
...
i++;
}
Note that if i
and j
were of the same type, then you could declare them both in the for-loop:
请注意,如果i
和j
是相同类型,那么您可以在 for 循环中声明它们:
for (int i = 0, j = 1; j < 3; j++, i++)
回答by Dani
I don't think you can define more than one type inside a for loop. only for(int i=0,j=3; j<7; j++, i++)
我认为您不能在 for 循环中定义多个类型。仅 for(int i=0,j=3; j<7; j++, i++)
回答by Bill W
Yes, it can be done. You can initialize variables of different types inside a for statement, but you cannot declarevariables of different types inside a for statement. In order to initialize variables of different types inside a for statement you mustdeclare all the types before the for loop. For example:
是的,这是可以做到的。您可以初始化不同类型的变量在for语句,但你不能申报的语句中不同类型的变量。为了在 for 语句中初始化不同类型的变量,您必须在 for 循环之前声明所有类型。例如:
int xx;
string yy;
for(xx=0, yy=""; xx<10; xx++)
{
....
}
[EDIT] Adding more information for completeness. This goes beyond what the OP requested, but may be helpful for others. It is simple to initialize variables of the same type in a for loop, just separate the initialization by commas. You can also have multiple variables changed in the third section. You cannot have multiple comma separated sections in the second, comparison section, but you can use && || and ! to make a complex Boolean section based on multiple variables.
[编辑] 为完整性添加更多信息。这超出了 OP 的要求,但可能对其他人有帮助。在for循环中初始化相同类型的变量很简单,只需用逗号分隔初始化即可。您还可以在第三部分更改多个变量。在第二个比较部分中不能有多个逗号分隔的部分,但可以使用 && || 和 !基于多个变量制作复杂的布尔部分。
for(int i=0, j=0, k=99; i<10 && k<200; i++, j++, k += 2)
However, it is not a good practice to make a for statement that is so complex that it is difficult to understand what is going on.
但是,创建一个复杂到难以理解发生了什么的 for 语句并不是一个好的做法。
回答by PhoenixLament
You can't define more then one variable in a loop structure. Try the code below:
您不能在循环结构中定义多个变量。试试下面的代码:
Option 1:One variable declared before loop and manually incremented in loop once per iteration.
选项 1:在循环之前声明一个变量,每次迭代在循环中手动递增一次。
MyClass i = 0;
for (int j = 1; j<3; j++)
{
//do stuff
i++
}
Option 2:both variables set before for loop and one incremented in loop structure, and other in loop manually.
选项2:两个变量都在for循环之前设置,一个在循环结构中递增,另一个在循环中手动。
MyClass i = 0;
int j = 1
for (; j<3; j++)
{
//do stuff
i++
}
Option 3:both variables are set before for loop structure, and both variables are incremented in the loop, leaving the loop to only check for a condition, which at this point you could just do a while loop.
选项3:两个变量都在for循环结构之前设置,两个变量在循环中递增,让循环只检查一个条件,此时你可以只做一个while循环。
MyClass i = 0;
int j = 1
for (; j<3)
{
//do stuff
j++
i++
}
Option 4:write as a while loop
选项 4:写为 while 循环
MyClass i = 0;
int j = 1
while (j<3)
{
//do stuff
j++
i++
}
回答by Hash
for (initializer; condition; iterator)
{
//body
}
The initializersection sets the initial conditions. The statements in this section run only once, before you enter the loop. The section can contain only one of the following two options.
的初始值设定部设定的初始条件。在进入循环之前,本节中的语句仅运行一次。该部分只能包含以下两个选项之一。
1)The declaration and initialization of a local loop variable. The variable is local to the loop and can't be accessed from outside the loop.
1)局部循环变量的声明和初始化。该变量是循环的局部变量,不能从循环外部访问。
2)Zero or more statement expressions from the following list, separated by commas:
2) 以下列表中的零个或多个语句表达式,用逗号分隔:
Assignment statement;
Invocation of a method;
Prefix or postfix increment expression, such as ++i or i++;
Prefix or postfix decrement expression, such as --i or i--;
Creation of an object by using new;
Await expression;
赋值语句;
方法的调用;
前缀或后缀增量表达式,如++i或i++;
前缀或后缀递减表达式,如--i或i--;
使用 new 创建对象;
等待表达;
As we know the compiler is not designed to accept the way we expect. So the above are the rules have to be followed before writing a initializer sectioninside a for loop.
正如我们所知,编译器的设计并不是为了接受我们期望的方式。所以以上是在for 循环中编写初始化部分之前必须遵循的规则。
回答by Hans Passant
Is it harmful?
有害吗?
Yes, very much so. A language parser has twoimportant duties. One is the job that everybody is familiar with, convert text into an executable program. But veryimportant as well is that it can detect an invalidprogram and generate a meaningful diagnostic to the programmer so he can fix his code.
是的,非常如此。语言解析器有两个重要的职责。一个是大家都熟悉的工作,把文本转换成可执行程序。但是很重要的,以及是,它能检测到的无效程序,并产生有意义的诊断给程序员,因此他可以修复他的代码。
At a very fundamental level, a language parser distinguishes between declarations, statementsand expressions. The curly-brace languages do obfuscate that distinction, you can turn any expression into a statement, simply by putting a semi-colon after it. And in some cases accept a declaration inside a statement, the for(;;) statement is a good example. Most plainly, this syntax is perfectly acceptable in the C or C++ languages:
在非常基础的层面上,语言解析器区分声明、语句和表达式。花括号语言确实混淆了这种区别,您可以将任何表达式转换为语句,只需在其后放置一个分号即可。在某些情况下,接受语句内的声明,for(;;) 语句就是一个很好的例子。最简单的是,这种语法在 C 或 C++ 语言中是完全可以接受的:
int x = 42;
x;
That's not exactly a good thing, it is nonsense code. The C# language upped the bar on that, it will reject that. But not:
这不是一件好事,它是无意义的代码。C# 语言提高了标准,它会拒绝。但不是:
int x = 42;
x++;
A special rule added to the language parser to accept this.
添加到语言解析器的特殊规则以接受这一点。
What none of the curly-brace languages will accept is turning a declaration into an expression. That way lies madness, dragons on the end of the map, ship falls off the edge with no good message left to report. The comma operator requires the lefthand and righthand operands to be expressions. A declaration is not an expression, end of story.
任何花括号语言都不会接受将声明转换为表达式。那种方式是疯狂的,地图末端的龙,船从边缘掉下来,没有好消息要报告。逗号运算符要求左手和右手操作数是表达式。声明不是表达,不是故事的结尾。
回答by Engin Kayraklioglu
This is not particularly my expertise, but here is my brainstorming about the topic:
这不是我的专长,但这是我对这个话题的头脑风暴:
In programmimng languages theory, a language's syntax must be defined without ambiguity. I cannot go into a very deep detail on it as it has been couple of years since I studied those topics. But you can check Backus-Naur Formthat is a notation technique to describe the "grammar" of the language. And that is the only one I am familiar with.
在程序设计语言理论中,语言的语法必须明确定义。我无法详细介绍它,因为我研究这些主题已经有几年了。但是您可以查看Backus-Naur Form,它是一种描述语言“语法”的符号技术。这是我唯一熟悉的。
So this description is used while parsing the code. And your parser must be able to relate every part of your code to the "rules" of the grammar. You can see C# Grammar here. It is somewhat in a similar form.
所以在解析代码时会用到这个描述。并且您的解析器必须能够将代码的每一部分与语法的“规则”相关联。您可以在此处查看 C# 语法。它有点类似的形式。
(1) Take a look at for-statement syntax
(1)看一下for语句的语法
for-statement:
for(for-initializer;for-condition;for-iterator)
embedded-statement
and then for-initializer syntax
然后是 for-initializer 语法
for-initializer:
local-variable-declaration
statement-expression-list
Note that statement-expression-list is only used in for loops. Also it is a comma separated list of statement-expressions.
请注意,语句表达式列表仅用于 for 循环。它也是一个逗号分隔的语句表达式列表。
I will leave some intermediate steps here but you can follow the grammar to get yourself more comfortable with the idea.
我会在这里留下一些中间步骤,但你可以按照语法来让自己更适应这个想法。
Hereis a good basic set of slides that demonstrates how complicated things can get even with a trivially simple grammar.
这是一组很好的基本幻灯片,演示了即使使用非常简单的语法,事情也会变得多么复杂。
(2) What we observed in 1 is what can we put for initializer part of the for loop. And we know that why your suggestion does not work. To be the bounty hunter let's analyze the reason of this design choice.
(2) 我们在 1 中观察到的是我们可以为 for 循环的初始化部分添加什么。我们知道为什么您的建议不起作用。作为赏金猎人,让我们分析一下这种设计选择的原因。
First, it is a design choice. You can design or find a language that allows that. It should be possible by changing the grammar, however some syntactical changes might be necessary. Here is why;
首先,它是一种设计选择。您可以设计或找到一种允许这样做的语言。应该可以通过更改语法来实现,但是可能需要进行一些语法更改。这是为什么;
If you are going to put multiple declaration statements, you might want to have something like declaration-list. And what you are going to use for seperator, you probably would not want to use ; because a semicolon is used for separating parts of the for loop. So, you can always go for comma, but if you use comma, then declaration-list rule can only be used in for loops, as it would be confusing to have comma separated declarations all over your code.
如果要放置多个声明语句,则可能需要声明列表之类的内容。您将要用于分隔符的内容,您可能不想使用 ; 因为分号用于分隔 for 循环的各个部分。因此,您始终可以使用逗号,但如果您使用逗号,则声明列表规则只能用于 for 循环,因为在您的代码中使用逗号分隔的声明会令人困惑。
Second, what is wrong with that? If you ask me, I do not see anything wrong either. If they have designed the language that it should have worked. (I am not saying that the sketch I just made is 100% correct, it can only be used as a starting point of a brainstorming session.)
其次,这有什么问题?如果你问我,我也看不出有什么不妥。如果他们设计了它应该工作的语言。(我并不是说我刚刚制作的草图是 100% 正确的,它只能用作头脑风暴会议的起点。)
Then, why did they chose not to? What pushed them to avoid that?
那么,他们为什么选择不这样做呢?是什么促使他们避免这种情况?
- How much complication do you introduce by adding that rule to your grammar?
- Do you also consider how many additional rules do you have to add to make the language unambiguous?
- Do you realize how complicated can already-existing rules get?
- How much workload that adds to your parser and then compiler?
- 通过将该规则添加到您的语法中,您引入了多少复杂性?
- 您是否还考虑过必须添加多少附加规则才能使语言明确无误?
- 您是否意识到现有规则会变得多么复杂?
- 给您的解析器和编译器增加了多少工作量?
After all these and many other considerations,
在所有这些和许多其他考虑之后,
- How much do you add to your language's usability, readability?
- Or do you even lose some readability?
- Do you consider, how frequently programmers need those types of for loops?
- Even if they do need it frequently, should you be encouring or discouraging them for that type of coding?
- 你对你的语言的可用性和可读性增加了多少?
- 或者你甚至会失去一些可读性?
- 您是否考虑过程序员需要这些类型的 for 循环的频率?
- 即使他们确实经常需要它,您应该鼓励还是劝阻他们进行这种类型的编码?
... and so many more questions like these, must be thougt carefully. And by looking at those questions and their analysis, I would say compiler designers' design choice was pretty much the most acceptable approach.
……还有很多像这样的问题,必须仔细考虑。通过查看这些问题及其分析,我会说编译器设计者的设计选择几乎是最可接受的方法。
回答by Fredrik Johansson
Of course it CAN be done. Just use the dynamickeyword:
当然可以做到。只需使用dynamic关键字:
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;
}
Have a great day!
祝你有美好的一天!
回答by Zorro Borealis
There is little reason not to have an alternate indexer initialized in-band. It keeps the environment clear of trashy var assignments.
没有什么理由不在带内初始化备用索引器。它使环境远离无用的 var 分配。
for (int x=0,y = 0; x < 100; x++)
{
if (true) { y++; }
// ... use y as a conditional indexer
// ... x is always the loop indexer
// ... no overflows
}
回答by Vladimir Liubimov
I usualy put the declarations before loop, and use additional curly braces to limit the scope of the declarations:
我通常将声明放在循环之前,并使用额外的花括号来限制声明的范围:
{ //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 ) )
{
//...
}
}