考虑下面的C#代码。
string[] stringArray = new string[10];
foreach (string s in stringArray)
s = "a new string"; // Compiler error - Can't assign to foreach iteration variable
现在考虑下面的有效的 C ++ / CLI代码。
array<String^>^ stringArray = gcnew array<String^>(10);
for each(String^% s in stringArray)
s = "a new string";
当foreach
与阵列型使用时,编译器将其转换为正常for
循环。 这个实现是同为C#和C ++ / CLI。 所以我想如果C ++ / CLI可以实现这一点,为什么不为C#编译器?
此错误是有道理的,当类型不是一个数组foreach
会被编译成GetEnumerator
通话,并使用枚举迭代。 但我认为它可以允许数组类型。
有什么想法吗?
作为一个侧面说明,下面是一个合法的C ++ / CLI代码太多,但不会产生预期的结果。
List<String^>^ stringList = gcnew List<String^>(10);
for each(String^% s in stringList)
s = "a new string"; // I think this should be prevented by compiler as it makes no sense.
这是因为C#是使用雾里看花(即魔术)。 你回来在foreach的变量不是数组中的实际项目,它是由迭代对象...还是其他什么东西制作的拷贝。 我们真的不知道(当然我们这样做,但我们必须打破了抽象层,并期待在迭代器对象的实现。)
如果你想改变这些值在数组中,你必须直接与阵列的接口来处理访问这些项目。 在C ++中出现这种情况,但主要是由错误(很多C ++的是这样的,原来的实现实际上是宏和预处理)。 在C#它明确定义不工作 - 这样一个编译器的消息。 (详见第5.3.3.16 规范。 )
我想你已经回答了你自己的问题,当你的状态,对于C ++的情况:
当foreach
与阵列型使用时,编译器将其转换为正常for
循环。
如果你的代码的C#作为一个for
循环,你可以做到这一点。
此上的评论MSDN页面解释更多,但它归结为一个事实,即通过修改字符串要更改集合的索引-这就是为什么环断裂。
重新霍根:是的,一个拷贝被它作出的。 事实上,当我跑进去(今天)我是指望它是一个modifieable副本:
foreach (string Token in tokenize(Command))
{
foreach (KeyValuePair<string, string> Replacement in TokensToReplace)
{
if (Token==Replacement.Key)
{
Token = Replacement.Value;
}
}
TokenList.Add(Token);
}
我认为这是不幸的是,这是行不通的。
Aaronaught,循环没有扭转它只是创建一个字符串变量“令牌”,并与记号化值初始化该功能。 之后,它没有任何与记号化的任何内部。 我试图让在是循环变量不应该是一些神奇的指针变成一个集但得到由“字符串令牌=”就好像它是在创建for或while循环创建的对象。
我不是想改变一些内部的收藏价值,但覆盖的局部变量。 它不应该有对收集数据的后果,因为指向旧字符串被分配后丢失。
在C ++中它的工作原理。
文章来源: Changing foreach iteration variable and implementation differences between C# and C++/CLI