【问题标题】:C#: Cannot assign to foreach iteration variableC#:无法分配给 foreach 迭代变量
【发布时间】:2010-02-04 00:51:11
【问题描述】:

我试图通过将其包装在一个循环中来压缩它:

       if (pos.X + pixelRadius < 0) {
            pos.X = bounds.Width - pixelRadius;
        } else if (pos.X + pixelRadius > bounds.Width) {
            pos.X = pixelRadius;
        }

        if (pos.Y + pixelRadius < 0) {
            pos.Y = bounds.Heigh - pixelRadius;
        } else if (pos.Y + pixelRadius > bounds.Height) {
            pos.Y = pixelRadius;
        }

我的第一直觉是做这样的事情:

        foreach (float coord in new float[] { pos.X, pos.Y }) {
            float upperBound = (coord == pos.X ? bounds.Width : bounds.Height);
            if (coord + pixelRadius < 0) {
                coord = upperBound - pixelRadius;
            } else if (coord + pixelRadius > upperBound) {
                coord = pixelRadius;
            }
        }

但是我当然会收到错误消息:

Cannot assign to 'coord' because it is a 'foreach iteration variable'

有什么方法可以将这段代码包装在一个循环中?或者可能不值得付出努力,保留第一种形式更具可读性。

对于那些好奇的人:是的,这是实现环绕。

【问题讨论】:

  • pos.Y = bounds.Width - pixelRadius 不应该是bounds.Height吗?
  • 这段代码是否正确?当离开左边界和 v.v. 时,它似乎迫使点跳到右边界。如果你想要模数学,为什么不使用 % 而不是 if?
  • @John:我认为你是对的。看起来他正在尝试实现环绕。
  • 好的,我添加了一个模数数学答案。
  • 尊重问题 title,这里有一个来自未来的相关回答链接:stackoverflow.com/questions/9780584/…

标签: c# loops xna foreach


【解决方案1】:

老实说,我认为第一个版本更具可读性。第二个版本在一个循环中批量填充然后......测试它是哪个循环元素???我闻起来像 for...case 反模式。

【讨论】:

  • Anon 是对的。特别是因为你只是这样做了两次。如果您必须这样做数百次,那么进行泛化工作会更有意义。
【解决方案2】:

我认为这是在做模数运算,所以这正是你想要的

pos.X %= bounds.Width;
pos.Y %= bounds.Height;

它没有给出与上述代码完全相同的行为,但如果你在做模之前调整边界并对该点应用一个偏差,它可以。

或者如果你需要有偏见的话

pos.X = ((pos.X - pixelRadius) % bounds.Width) + pixelRadius;
pos.Y = ((pos.Y - pixelRadius) % bounds.Height) + pixelRadius;

模数数学是一种更好的环绕方式。它更清晰,并且没有分支。

【讨论】:

  • 嗯,这很有趣。谢谢。
  • 如果 pos.X 或 pos.Y 为负数怎么办?
  • 试试吧。模数学适用于负数(结果总是正数)
【解决方案3】:

即使你可以改变坐标,因为它是一个浮点数,你实际上只是在修改一个副本而不是 pos 中的值。最好的办法是创建一个新方法。

【讨论】:

    【解决方案4】:

    我会保留它的原始形式。当您处于上述循环中时,coordpos.Xpos.Y 变量的COPY,因为它们是Value Types。这意味着即使您可以更新坐标...您也不会更新 pos.Xpos.Y,而是更新它们的本地循环副本。

    【讨论】:

      【解决方案5】:

      循环是个坏主意。

      您现在拥有的代码看起来有问题,但它的结构比一些不自然的循环使用要好。

      如果我理解你想要做什么,我认为你应该有这样的东西

      (我关注的是坐标 X。如果是坐标 Y,则类似)

      pos.X += pixelRadius;
      if(pos.X < 0) {
          pos.X += bounds.Width;
      } else if (pos.X > bounds.Width) {
          pos.X -= bounds.Width;           
      }
      

      如果 |pixelRadius| 这将起作用

      模数运算符使事情变得更容易,尤其是如果 |pixelRadius| > bounds.With,但要小心负数的情况。您必须确切地知道您的语言实现将如何处理它们

      使用模数运算符我会这样做

      pos.X = (pos.X + pixelRadius) % bounds.Width;
      if(pos.X < 0) pos.X += bounds.Width;
      

      【讨论】:

        猜你喜欢
        • 2020-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-10
        • 2021-03-10
        相关资源
        最近更新 更多