5

C#ジェネリックに関するヘルプを求めています。私は Unity3D で作業しており、Unity3D には BiLerp 関数がないため、BiLerp 関数を使用しています。

public Vector3 BiLerp(Vector2 _uv, Vector3 _00, Vector3 _01, Vector3 _10, Vector3 _11)
{
    return _00 * (1 - _uv.x) * (1 - _uv.y) +
           _10 * _uv.x * (1 - _uv.y) +
           _01 * _uv.y * (1 - _uv.x) +
           _11 * _uv.x * _uv.y;
}

ただし、この機能をもう少し堅牢にしたいと考えています。

  1. 浮動小数点数で乗算できる任意の型を受け入れるように、ジェネリックにしたいと思います
  2. これを静的にするべきかどうかはわかりません。メンバー変数を使用しないため、はい、と仮定しています。これが格納されているクラスも静的である必要がある場合、クラスはユニティ (Matrix2x2) などによって省略された数学ヘルパー用になります。
  3. この場合、C# の const はどのように機能しますか?
  4. C++ では、参照によってパラメーターを渡します。C# が既にこれを行っていると仮定して正しいですか? ref キーワードは他の闇の魔法のツールですか?

他に提案があれば、お気軽にどうぞ。私はC#で6週間しか働いていないので、どんな提案も使うことができます.

4

4 に答える 4

6
  1. 乗算を行うデリゲートを渡すことでこれを機能させることは可能ですが、かなり遅くなります。実際には、代わりに複数のオーバーロードを記述したほうがよいと思います。

  2. はい、そうするべきです。また、それを静的クラスに入れる必要があります。(IMHO!)拡張メソッドにすることを提案するつもりでしたが、リフレクションでは、パラメータが多すぎて便利になりません。

  3. C# の const は C++ の const に似ていますが、一般的なコンセンサスは、それらは非公開 (またはおそらく内部) であるべきだということです。

  4. 実はVector2とVector3は構造体なので値渡しです。それらを参照渡しする場合は、次のrefキーワードを使用します。

    public Vector3 BiLerp(
        ref Vector2 _uv, ref Vector3 _00, ref Vector3 _01,
        ref Vector3 _10, ref Vector3 _11)`
    

ただし、そうする理由は 2 つだけです (構造体の場合)。

  1. 渡される元の値を変更したいためです。

  2. 参照 (つまり、C++ 用語ではポインター) を渡すだけで高速化します。

最初のものはあなたのコードには当てはまらず、2 番目のものはそのような小さな構造体には無意味に思えます (実際、すべての構造体は小さくあるべきなので、適切に設計された構造体にはほとんど適用されません)。

于 2013-03-23T11:25:27.727 に答える
4

浮動小数点数で乗算できる任意の型を受け入れるように、ジェネリックにしたいと思います

残念ながら、C# のジェネリック型システムは、この種の制約をサポートしていません。これは、C# チームが検討したかなり頻繁に要求される機能ですが、基になる CLR 型システムで多くの作業が必要になります。今後実装される可能性はありますが、私だったらその日が待ち遠しいです。

これを静的にするべきかどうかはわかりません。メンバー変数を使用しないため、はい、と仮定しています。

はい、静的にします。

これが格納されているクラスも静的である必要がある場合、クラスは数学ヘルパー用になります。

はい。

この場合、C# の const はどのように機能しますか?

C# の const は C++ の const とは異なります。それははるかに簡単です。C# では、const フィールドまたは local は、コンパイル時の定数番号または文字列の名前であり、話の終わりです。(わかりました、参照型の const を持つこともできますが、それは null でなければならないので、それほど興味深いことではありません。) この「ここに参照がありますが、それを変更するメソッドを呼び出すことはできません」というルールはありません。 C#.

ベスト プラクティスは、最初からすべての値の型を不変にすることです。そのため、C++ スタイルの const は実際には必要ありません。

フィールドを「読み取り専用」とマークすると、コンストラクターでのみ変更できるようになります。

C++ では、参照によってパラメーターを渡します。C# が既にこれを行っていると仮定するのは正しいですか?

いいえ。値型は値渡しです。

ref キーワードは、他の闇の魔法のツールですか?

ref キーワードは C++ の参照と同じです: 1 つの変数を別の のエイリアスにします。通常、C# では、呼び出し元から提供された変数を変更する必要がある場合にのみ使用します。前に述べたように、C# には "const 参照" という C++ の概念はありませんが、C# の値の型は小さいと想定されているため、値渡しが効率的であるため、通常は "const の概念は必要ありません。参照」を使用して、「パフォーマンスのためにこれを参照渡ししたいが、実際には変数を変更したくない」と言います。

于 2013-03-23T16:51:11.267 に答える
2

1)フロートで乗算できる任意の型を受け入れるようにテンプレート化したいと思います

C# のジェネリックの現在の実装でそれが可能かどうかはわかりません。を定義できませT where T : float。コンパイラはそれを教えてくれますonly class or interface could be specified as constraint

2) これを静的にするべきかどうかはわかりません。...これが格納されているクラスも静的にする必要があります

静的メソッドが 1 つあるため、クラスを静的にはしません。あなたが定義したメソッドに問題はありません。メンバーを使用しないため、静的にすることは理にかなっています (ヘルパー メソッドのように見えます)。マシューズの回答で提案されているように、それを拡張メソッドにすることもできます。何かのようなもの:

public static class Vector2Ext
{
    public static Vector3 BiLerp(
        this Vector2 _uv,
        Vector3 _00,
        Vector3 _01,
        Vector3 _10,
        Vector3 _11)
    {
        // your implementation
    }
}

そうすればBiLerp、メソッドを Vector2 のメソッドとして呼び出すことができます。

Vector2 vector2 = ...;
vector2.BiLerp(_00, _01, _10, _11);

そのように設計することが理にかなっている場合は、おそらくこのケースで最も適切に判断できます。

3) この場合、C# の const はどのように機能しますか?

少し曖昧で、あなたが何を意味するのかわかりません。ここでMSDNは役に立ちますか?

4) C++ では、参照によってパラメーターを渡します。C# が既にこれを行っていると仮定して正しいですか? ref キーワードは他の闇の魔法のツールですか?

それ自体が話題です。refキーワードを使用する場合は、型を参照として渡します。VectorXD不変型である場合は理にかなっています。呼び出し側で valuetype の値が必要な場合は、ref で渡します。Vector3Dコードを見て、いくつかの値を渡し、それらを使用して a を計算し、それを返すと解釈します。ここの必要性がわかりませんref。しかし、私はあなたの質問を再び誤解しているかもしれません。おそらく、 MSDNは の使用法を理解するのに役立ちますref

于 2013-03-23T11:25:17.820 に答える
1

テンプレートは C++ で知られているため、C# にはテンプレートがありません。この用語はgenerics、C++ コードのテンプレートよりも少し制約があります。必要なものについては、型から継承することは不可能であり、float数値型に一般的な制約を設定することもできません。C# (および一般的な .NET) の値の型は、型の継承によって拡張できません。floatValueType

提案として、floatordoubleを直接使用することができます。C# は、他のすべての数値型 (おそらく を除く)floatとの間で自動キャストを実行します。doubledecimal

于 2013-03-23T11:26:11.533 に答える