【发布时间】:2009-06-09 22:39:47
【问题描述】:
我使用 XNA,我经常做的一件事就是将数据作为 Vector2s 传递。现在,XNA 中的很多对象(例如图形设备等),包含一个告诉您视口大小的 Vector2,它们提供了单独的 Width 和 Height 方法。有什么方法可以向它们添加 Vector2 属性,这样我就可以在不需要每次需要时手动构建新的 vector2 的情况下获取该数据?我想我想要的是“扩展属性”之类的东西......
【问题讨论】:
我使用 XNA,我经常做的一件事就是将数据作为 Vector2s 传递。现在,XNA 中的很多对象(例如图形设备等),包含一个告诉您视口大小的 Vector2,它们提供了单独的 Width 和 Height 方法。有什么方法可以向它们添加 Vector2 属性,这样我就可以在不需要每次需要时手动构建新的 vector2 的情况下获取该数据?我想我想要的是“扩展属性”之类的东西......
【问题讨论】:
Vector2 是一种值类型……老实说,您不必太担心创建新实例,因为它们是在堆栈上创建的。每次您可以使用 .Vector 属性时,它都会创建一个新实例。
您不必担心它,因为值类型不会调用垃圾收集器。因此,尝试实例化一次的最大理由无效(即 GC)。
话虽如此,对于矩阵等较大的结构,您可能需要考虑通过引用传递它们以避免堆栈上的新分配。
【讨论】:
就效率而言,最好只使用 Width 和 Height 属性来做任何你可以做的事情。但是,不要忘记 #1 优化规则:don't do it。
包装类的想法是一个很好的解决方案,但我只是想提出一个全局可转换结构的想法。我使用这样的东西来消除对向量->点和点->向量转换的担忧(至少在调试期间):
[DebuggerDisplay("{value}")]
public struct PointyVector
{
Vector2 value;
//Constructors:
public PointyVector(System.Drawing.Point point)
{
value = new Vector2(point.X, point.Y);
}
public PointyVector(Point point)
{
value = new Vector2(point.X, point.Y);
}
public PointyVector(Vector2 vector)
{
value = new Vector2(vector.X, vector.Y);
}
//Implicit conversion operators:
public static implicit operator PointyVector(Vector2 vector)
{
return new PointyVector(vector);
}
public static implicit operator PointyVector(System.Drawing.Point point)
{
return new PointyVector(point);
}
public static implicit operator PointyVector(Point point)
{
return new PointyVector(point);
}
public static implicit operator Vector2(PointyVector vector)
{
return vector.value;
}
public static implicit operator Point(PointyVector vector)
{
return new Point((int)vector.X, (int)vector.Y);
}
}
这种结构,在 Vector2 和 Point 之间添加了一些二元运算符,使得 Xna 中的向量/点的东西变得更加简单,但它也可能导致转换模糊、舍入错误、截断损失和所有其他乐趣与数字转换相关的问题。所有这些问题都可以通过显式转换轻松解决,但请注意,如果您在使用此结构时看到“奇怪的数字”,则可能是由于转换过程中的精度损失。
【讨论】:
您可以使用 Michael 的方法,但实际上每次都会构建一个新的 Vector2。如果你真的只希望 Vector2 被创建一次,你可以包装你想要的类,并提供你自己的 Vector2 属性:
public class GraphicsDeviceWrapper
{
private Vector2 vector;
public GraphicsDeviceWrapper(GraphicsDevice device)
{
this.vector = new Vector2(device.Viewport.Width, device.Viewport.Height);
this.Device = device;
}
public Vector2 Vector
{
get{return this.vector;}
}
public GraphicsDevice Device
{
get; private set
}
}
【讨论】:
不支持扩展属性,但您仍然可以编写扩展方法:
class ExtensionMethods
{
public static Vector2 GetViewSize(this GraphicsDevice device)
{
return new Vector2(device.Viewport.Width, device.Viewport.Height);
}
}
【讨论】: