gpt4 book ai didi

c# - 更改 foreach 迭代变量和 C# 与 C++/CLI 之间的实现差异

转载 作者:太空宇宙 更新时间:2023-11-03 18:48:36 25 4
gpt4 key购买 nike

考虑以下 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.

最佳答案

这里似乎有三个不同的问题:

  1. 为什么 C++ 允许您为每个 迭代变量分配一个

  2. 为什么不是 C#?

  3. 为什么 C++ 和 C# 编译器的行为不同?



答案相当简单:




  1. 因为 C++ 团队没有决定明确禁止它,而且从技术上讲迭代变量只是一个局部变量 - 它没有得到特殊处理。


  2. 因为 C# 团队确实决定禁止它,因为(很可能)他们认为它会导致错误或不正确的代码。分配给任何循环变量通常被认为是一种代码味道。


  3. 因为C++团队和C#团队是不同的团队。 C++ 一直是一种允许你搬起石头砸自己的脚的语言,如果你愿意的话,甚至可以把上膛的枪交给你。 C# 经常会尝试执行“正确的代码”规则。




这里可能还有另外一个问题,就是:




  • 如果 C# 不允许赋值,为什么要将 foreach 编译成 for?或者,反过来 - 如果它就是这样编译的,为什么不允许这样做?



这个问题实际上有两个答案:




  • 因为它更快。 foreachIEnumerable 进行操作,这需要实例化一个新的IEnumerator 类。数组类型是编译器识别的特殊类型,所以如果编译器已经知道 IEnumerable 实际上是一个 Array,那么它会编译为索引访问,这很更便宜。



    然而,这个小的性能调整只是一个实现细节;它不是规范的一部分,如果您能够编写依赖于特定实现的代码,C# 团队以后将无法在不破坏现有代码的情况下更改该实现。他们当然希望避免这种情况。


  • 因为它实际上并不像人们想象的那样重要。如果您可以在 C# 中进行赋值,您实际上不会修改数组,而只会修改最初保存数组内容的局部变量的内容。这再次属于“使编写错误代码变得困难”的类别 - 如果构造确实允许您分配给变量,一些程序员可能会认为这会实际上改变集合,这将是错误的。




我认为这应该可以很好地解释它。








关于c# - 更改 foreach 迭代变量和 C# 与 C++/CLI 之间的实现差异,我们在Stack Overflow上找到一个类似的问题:

https://stackoverflow.com/questions/2037988/




25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com