我正在为CAD系统编写插件。不幸的是,这个系统的API很糟糕。所以,我写了Vector3d类的扩展。这是(C#代码):
/// <summary>
/// Normalizes the vector by dividing it’s all coordinates with the vector's norm.
/// </summary>
/// <param name="v">
/// This vector.
/// </param>
/// <returns>
/// Returns vector's norm.
/// </returns>
public static double Normalize(this Vector3d v)
{
var norm = v.Norm();
var invNorm = 1.0 / norm;
v.X *= invNorm;
v.Y *= invNorm;
v.Z *= invNorm;
return norm;
}
但是我有一个问题:当这个方法执行时,矢量的坐标会改变。但是,当方法执行时,矢量坐标具有原始值。
我对其他扩展方法没有任何问题。
答案 0 :(得分:1)
在假设Vector3d是结构的情况下工作:
参数(无论是否为扩展方法的'this'参数)都按值传递。您使用的参数实际上是原始vector3的副本。
建议将其更改为:
public static double NormalizeVector3d(ref Vector3d v);
或者:
public static Vector3d GetNormalizedVector3d(Vector3d v, out double norm);
无论哪种方式,都无法使用扩展方法进行呼叫。
答案 1 :(得分:1)
正如leppie所提到的,Vector3d
可能是struct,而不是一个类。
这意味着它是value type,并将其作为参数传递给您的扩展方法,可以有效地创建该对象的副本。您的扩展方法会更改副本,然后在退出方法时将其丢弃。
我找不到这个.NET API的良好API参考,但这也可能是您认为API“不好”的原因。修改Vector3d的方法将返回原始向量的副本,而不是对对象本身进行操作。或者,他们可以使用参考参数,这也是你可以做的:
public static double Normalize(ref Vector3d v)
假设它是一个结构体(如果没有更多信息我想不到另一种解释),API的创建者应该使结构不可变。可变结构是这些问题的处方。
就个人而言,我可能会写这样的方法:
public static Vector3d Normalize(this Vector3d v, out double norm)
{
norm = v.Norm();
var invNorm = 1.0 / norm;
// Using a constructor with x, y, z parameters would be preferable,
// if it exists.
v.X *= invNorm;
v.Y *= invNorm;
v.Z *= invNorm;
return v;
}
与ref
选项不同,它可以作为扩展方法编写。