1

请参阅以下代码:

    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迭代不起作用。
  • 在将向量添加到列表之前创建规范化向量而不是遍历列表确实有效。

为什么迭代不起作用?

4

3 回答 3

4

循环创建序列元素的foreach本地副本。您只对副本进行规范化。

您将需要执行以下操作:

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

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

于 2012-11-17T10:16:11.283 回答
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[]属性),它再次返回原始对象的副本

于 2012-11-17T10:38:02.613 回答
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();
}
于 2012-11-17T10:20:36.697 回答