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 に答える