为什么这个循环不会规范化我的Vector2列表?

时间:2012-11-17 10:12:56

标签: c# xna foreach

请参阅以下代码:

    List<Vector2> axes = new List<Vector2>();
    axes.Add(TopRight() - TopLeft());
    axes.Add(BottomLeft() - TopLeft());
    axes.Add(otherRectangle.TopRight() - otherRectangle.TopLeft());
    axes.Add(otherRectangle.BottomLeft() - otherRectangle.TopLeft());
    // Try normalizing vectors?
    foreach (Vector2 axis in axes)
    {
        axis.Normalize();
    }

Vector2.Normalize()方法是一个void方法,它规范了它所调用的向量。但由于某种原因,当我执行此循环时,它不会对矢量进行标准化。我只是不能以这种方式修改列表吗?

一些奇怪的事情:

  • 使用for循环进行迭代,即axis[i].Normalize()不起作用。
  • 使用内置的List<T>.ForEach迭代器进行迭代不起作用。
  • 在将向量添加到列表之前创建向量的规范化,而不是迭代列表 工作。

为什么迭代不起作用?

3 个答案:

答案 0 :(得分:4)

foreach循环创建序列元素的本地副本。您只能将副本标准化。

您需要执行以下操作:

for(int i=0; i<axes.Count; i++)
    axes[i] = Vector2.Normalize(axes[i]);

这种不直观的行为再次证明了为什么改变结构的实例方法是个坏主意。

答案 1 :(得分:3)

正如CodesInChaos所说,Vector2.Normalize是一种设计糟糕的方法(这个决定的原因可能出于性能考虑,但这对我们没有帮助。)

因此,它变异它所使用的对象。但是,该对象是foreach外观中原始对象的副本。因此,您的代码只会改变对象,而不是实际列表中的对象。

唯一的解决方法是对列表中的项目使用索引for循环:

for (int i = 0; i < axes.Count; i++) {
    Vector2 copy = axes[i];
    copy.Normalize();
    axes[i] = copy;
}

在这里,我们修改了一个副本,但之后我们将它复制回实际的矢量中。请注意,我们不能只是通过编写axes[i]来修改axes[i].Normalize() - 这可以说是(并且在我看来) .NET中的另一个设计缺陷。原因是axes[i]操作是属性访问(访问this[]属性),再次返回原始对象的副本

答案 2 :(得分:0)

更多编辑: 首先尝试规范化矢量,然后将它们添加到列表...

List<Vector2> axes = new List<Vector2>();

Vector2 tempTopRightTopLeftVector = TopRight() - TopLeft();
tempTopRightTopLeftVector.Normalize();
axes.Add(tempTopRightTopLeftVector);

Vector2 tempBottomLeftTopRightVector = BottomLeft() - TopLeft();
tempBottomLeftTopRightVector.Normalize();
axes.Add(tempBottomLeftTopRightVector);

// and so on for other vectors...

更多编辑:

尝试使用其他类型的集合。数组例如:

Vector2[] axes = new Vector2[] {
   TopRight() - TopLeft(),
   BottomLeft() - TopLeft(),
   otherRectangle.TopRight() - otherRectangle.TopLeft(),
   otherRectangle.BottomLeft() - otherRectangle.TopLeft()
}
for(int i=0; i<axes.Length; i++)
{
   axes[i].Normalize();
}