0

我正在为 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;
}

但是我有一个问题:当这个方法执行时,向量的坐标会改变。但是,当方法执行后,向量的坐标具有原始值。

我对其他扩展方法没有问题。

4

2 回答 2

1

在 Vector3d 是一个结构的假设下工作:

参数(无论是否是扩展方法的“this”参数)按值传递。您使用的参数实际上是原始vector3 的副本。

建议改成:

public static double NormalizeVector3d(ref Vector3d v);

或者:

public static Vector3d GetNormalizedVector3d(Vector3d v, out double norm);

无论哪种方式,都无法使用扩展方法进行调用。

于 2013-03-28T07:14:14.343 回答
1

正如 leppie 提到的,Vector3d可能是一个struct,而不是一个类。

这意味着它是一个值类型,并且将它作为参数传递给您的扩展方法有效地创建了对象的副本。您的扩展方法会更改副本,然后在退出方法时将其丢弃。

我找不到此 .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选项不同,它可以编写为扩展方法。

于 2013-03-28T07:15:14.443 回答