我发现自己这样做了:
string states = "this,that,theother";
foreach(string state in states.Split(','))
{
}
我想知道;是否在每个foreach循环上拆分states
字符串?
这个例子在c#中,但其他编程语言的表现有所不同吗?
PHP和JavaScript是否在每个foreach循环上拆分?
PHP :每次循环都会爆炸吗?
$states = "this,that,theother";
foreach(explode(',', $states) as $state)
{
}
答案 0 :(得分:1)
不,分裂发生一次。
states.Split(',')返回一个数组。 .NET中的数组实现IEnumerable
通常,.NET集合是向量,数组或实现IEnumerable的其他集合,或者提供GetEnumerator()方法,该方法返回具有属性Current和方法MoveNext()的枚举器对象。在某些情况下,编译器将生成使用GetEnumerator()的代码,在其他情况下,它将使用ldelem.ref发出简单的向量指令,换句话说,将foreach转换为for循环。
在foreach()语句的开头,迭代的主题states.Split()将只被评估一次。在C#中,在编译时决定我们迭代什么类型的容器,并选择策略。编译器生成代码以将数组(或其他可枚举结果)返回到临时变量中,然后循环继续逐个访问数组中的第N个项。一旦范围被销毁," temp"容器是垃圾收集。
现在编译器并不总是使用IEnumerator。它可以将foreach()转换为for()循环。
考虑:
string states = "1,2,3";
foreach (var state in states.Split(','))
{
Console.WriteLine(state);
}
示例MSIL:
IL_0017: ldloc.s CS$0$0000
IL_0019: callvirt instance string[] [mscorlib]System.String::Split(char[]) // happens once
IL_001e: stloc.s CS$6$0001 // <--- Here is where the temp array is stored, in CS$6$0001
IL_0020: ldc.i4.0
IL_0021: stloc.s CS$7$0002 // load 0 into index
IL_0023: br.s IL_003a
IL_0025: ldloc.s CS$6$0001 // REPEAT - This is the top of the loop, note the Split is above this
IL_0027: ldloc.s CS$7$0002 // index iterator (like (for(int i = 0; i < array.Length; i++)
IL_0029: ldelem.ref // load the i-th element
IL_002a: stloc.1
IL_002b: nop
IL_002c: ldloc.1
IL_002d: call void [mscorlib]System.Console::WriteLine(string)
IL_0032: nop
IL_0033: nop
IL_0034: ldloc.s CS$7$0002
IL_0036: ldc.i4.1 // add 1 into index
IL_0037: add
IL_0038: stloc.s CS$7$0002
IL_003a: ldloc.s CS$7$0002
IL_003c: ldloc.s CS$6$0001
IL_003e: ldlen
IL_003f: conv.i4
IL_0040: clt // compare i to array.Length
IL_0042: stloc.s CS$4$0003 // if i < array.Length
IL_0044: ldloc.s CS$4$0003 // then
IL_0046: brtrue.s IL_0025 // goto REPEAT (0025) for next iteration
答案 1 :(得分:1)
不,两种语言都不会每次都分裂字符串(这很荒谬)。
来自PHP manual:
在每次迭代时,将分配当前元素的值
$value
并且内部数组指针前进一个(所以在 下一次迭代,你将看到下一个元素。)
请注意对内部数组指针的引用。如果每次迭代都在不同的数组上运行,那么更改内部数组指针将毫无意义。
来自ES5注释reference:
当使用一个或两个参数调用
forEach
方法时, 采取以下步骤:
- 让
醇>O
成为调用ToObject
传递this
值作为参数的结果。
此处O
表示正在迭代的对象;这个结果只计算一次。
答案 2 :(得分:0)
var enumerator = states.Split(',').GetEnumerator();
while (enumerator.MoveNext()) {
string state = enumerator.Current;
...
}
在此处查看更多详情:http://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx