为什么在C#foreach语句迭代变量只读? [英] Why is The Iteration Variable in a C# foreach statement read-only?

查看:308
本文介绍了为什么在C#foreach语句迭代变量只读?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解,C#的foreach迭代变量是不可变的。

As I understand it, C#'s foreach iteration variable is immutable.

这意味着我不能修改这样的迭代器:

Which means I can't modify the iterator like this:

foreach (Position Location in Map)
{
     //We want to fudge the position to hide the exact coordinates
     Location = Location + Random();     //Compiler Error

     Plot(Location);
}

我不能直接修改迭代变量,而是,我必须用一个for循环

I can't modify the iterator variable directly and instead, I have to use a for loop

for (int i = 0; i < Map.Count; i++)
{
     Position Location = Map[i];
     Location = Location + Random();

     Plot(Location);        
     i = Location;
}

这是一个C ++背景的,我看到的foreach作为替代for循环。但与上述限制,我通常回退到使用的for循环。

Coming from a C++ background, I see foreach as an alternative to the for loop. But with the above restriction, I usually fallback to using the for loop.

我很好奇,是什么使得后面的迭代器不可变的理由?

I'm curious, what is the rationale behind making the iterator immutable?


编辑:

此问题更是一个好奇的问题,而不是作为编码问题。我AP preciated编码的答案,但我不能将它们标记为答案。

This question is more of a curiousity question and not as a coding question. I appreciated the coding answers but I can't mark them as answers.

另外,上面的例子是过于简单化。这里是什么,我想做一个C ++的例子:

Also, the example above was over-simplified. Here is a C++ example of what I want to do:

// The game's rules: 
//   - The "Laser Of Death (tm)" moves around the game board from the
//     start area (index 0) until the end area (index BoardSize)
//   - If the Laser hits a teleporter, destroy that teleporter on the
//     board and move the Laser to the square where the teleporter 
//     points to
//   - If the Laser hits a player, deal 15 damage and stop the laser.

for (int i = 0; i < BoardSize; i++)
{
    if (GetItem(Board[i]) == Teleporter)
    {
        TeleportSquare = GetTeleportSquare(Board[i]);
        SetItem(Board[i], FreeSpace);
        i = TeleportSquare;
    }

    if (GetItem(Board[i]) == Player)
    {
        Player.Life -= 15;
        break;
    }
}

我做不到上面的C#的foreach,因为我的迭代器是不可变的。我认为(纠正我,如果我错了),这是特定的foreach的语言设计的。

I can't do the above in C#'s foreach because the iterator i is immutable. I think (correct me if I'm wrong), this is specific to the design of foreach in languages.

我感兴趣的是,为什么在foreach迭代器是不可变的。

I'm interested in why the foreach iterator is immutable.

推荐答案

让我们用愚蠢,但说明性的例子开始了:

Lets start out with a silly but illustrative example:

Object o = 15;
o = "apples";

在任何时候做我们得到的IM pression我们刚满15号到苹果的字符串。我们知道, 0 只是一个指针。现在,让我们在迭代器的形式做到这一点。

At no point do we get the impression that we just turned the number 15 into a string of apples. We know that o is simply a pointer. Now lets do this in iterator form.

int[] nums = { 15, 16, 17 };

foreach (Object o in nums) {
     o = "apples";
}

此外,这真的无所作为。或者至少它的将会的一事无成了编译它。这当然不会插入我们的字符串插入int数组 - ,这是不允许的,我们知道, 0 只是一个指针,反正

Again, this really accomplishes nothing. Or at least it would accomplish nothing were it to compile. It certainly wouldn't insert our string into the int array -- that's not allowed, and we know that o is just a pointer anyway.

让我们把你的例子:

foreach (Position Location in Map)
{
     //We want to fudge the position to hide the exact coordinates
     Location = Location + Random();     //Compiler Error

     Plot(Location);
}

被这个编译时,位置在您的示例明星出指的是值地图,但随后你改变它来指一个新的位置(由加法运算符隐式创建)。功能上它等同于本(它编译):

Were this to compile, the Location in your example stars out referring to a value in Map, but then you change it to refer to a new Position (implicitly created by the addition operator). Functionally it's equivalent to this (which DOES compile):

foreach (Position Location in Map)
{
     //We want to fudge the position to hide the exact coordinates
     Position Location2 = Location + Random();     //No more Error

     Plot(Location2);
}

那么,为什么微软禁止您重新分配用于迭代指针?清晰度一件事 - 你不希望人们赋予它思想,他们已经改变了循环中的地位。易于实现的另一个:变量可能​​会隐藏一些内部逻辑表明正在进行循环的状态。

So, why does Microsoft prohibit you from re-assigning the pointer used for iteration? Clarity for one thing -- you don't want people assigning to it thinking they've changed your position within the loop. Ease of implementation for another: The variable might hide some internal logic indicating the state of the loop in progress.

但更重要的是,没有任何理由让你的需要的分配给它。它重新presents循环序列的当前元素。值分配给它打破了单一职责原则或卷毛定律如果你遵循编码恐怖。变量应该是说只有一件事。

But more importantly, there is no reason for you to want to assign to it. It represents the current element of the looping sequence. Assigning a value to it breaks the "Single Responsibility Principle" or Curly's Law if you follow Coding Horror. A variable should mean one thing only.

这篇关于为什么在C#foreach语句迭代变量只读?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆