14

たとえば、次の行に沿って:

public bool Intersect (Ray ray, out float distance, out Vector3 normal)
{

}

public IntersectResult Intersect (Ray ray)
{

}

public class IntersectResult
{
    public bool Intersects {get;set;}
    public float Distance {get;set;}
    public Vector3 Normal {get;set;}
}

明快さ、使いやすさ、そして最も重要なパフォーマンスの両方でどちらが優れています。

4

8 に答える 8

16

結合型を使用しますが、その理由を説明します。値の計算では、一連の変数を変更するのではなく、値を返す必要があるためです。複数の変数を変更する必要がある場合、多数の変数を変更してもスケーリングしません。次のものが何千も必要だとします。

IEnumerable<Ray> rays = GetAThousandRays();
var intersections = from ray in rays 
                    where Intersect(ray, out distance, out normal)
                    orderby distance ...

クエリを実行すると、同じ 2 つの変数が繰り返し変更されます。変異している値に基づいて注文しています。これは混乱です。物事を変更するクエリを作成しないでください。それは非常に紛らわしいです。

あなたが望むものは:

var intersections = from ray in rays 
                    let intersection = Intersect(ray)
                    where intersection.Intersects
                    orderby intersection.Distance ...

突然変異なし; 一連の値を変数としてではなく、値として操作します。

また、そのブール値フラグを取り除き、値を不変の構造体にする傾向もあります。

// returns null if there is no intersection
Intersection? Intersect(Ray ray) { ... }

struct Intersection 
{
    public double Distance { get; private set; }
    public Vector3 Normal { get; private set; }
    public Intersection(double distance, Vector3 normal) : this()
    {
        this.Normal = normal;
        this.Distance = distance;
    }
} 
于 2011-03-10T22:14:54.267 に答える
10

複合タイプを使用します。

オブジェクトを使用すると、ビヘイビアーをアタッチして、任意の複雑なオブジェクトを返すことができます。将来、メソッドをリファクタリングして、戻り値を変更したくなるかもしれません。それらを戻りオブジェクトにラップし、そのオブジェクトに動作を追加することで、このリファクタリングを大幅に透過的にすることができます。

タプルなどを使用するのは魅力的です。ただし、リファクタリングの作業はしばらくすると頭痛の種になります (ここでの経験から言えば、この間違いをまた犯したばかりです) 。

于 2011-03-10T21:22:43.767 に答える
6

結合型を返すことをお勧めします。少なくとも、メソッド シグネチャがよりクリーンになり、プログラマがメソッドを呼び出すときに行う作業が少なくなります。EG: 変数を宣言して初期化する必要がないため、呼び出しコードが煩雑になります。

于 2011-03-10T21:20:58.983 に答える
5

好みの問題だと言う人もいますが、複雑なオブジェクトを返す方が分かりやすさだけでなく、メンテナンスの面でも優れていると思います。

出力として別のデータを追加する必要がある場合は、余分な応答のコードを追加するだけでなく、メソッドのシグネチャを変更する必要があります。複雑な出力タイプではそうではありません。さらに、(単体テスト用に) 出力パラメーターをモックすることはより困難です。また、「単純な」哲学を壊しているようにも見えます.入力が1つしか必要ないときに、出力パラメータを設定するという手間がかかります. OOP 言語の強みは、型を作成することです。私の意見では、その方法を使用します。

2 つのパフォーマンスの違いはごくわずかです。

于 2011-03-10T21:22:48.427 に答える
3

代わりに IntersectResult クラスを作成する代わりに Tuple を使用できます。

参照:

http://msdn.microsoft.com/en-us/library/system.tuple.aspx

ただし、私は間違いなく、out パラメーターよりも複雑な型を返すことに傾倒しています。

于 2011-03-10T21:21:31.637 に答える
3

記録のために: 魔法のトリオ (明快さ、使いやすさ、パフォーマンス) の良い例を見つけるのは難しいです。

明らかに、2 番目の例は最初の 2 つを提供しますが、最初の例はより優れたパフォーマンスを提供します。これが無視できるかどうかはわかりません。たぶんベンチマークテストを実行して見つけてください。

私が言えることは、ヒープへの割り当てはスタックよりもコストがかかるため、結果の型を小さなサイズの構造体にすると、パフォーマンス ポイントをいくらか節約できるということです。繰り返しになりますが、値型からデータをコピーすると、ヒープ割り当てのペナルティを上回る可能性がありますが、十分に小さく保っている場合はそうではない可能性があります。さらに、おそらくその型を不変にしたいでしょう。

于 2011-03-10T21:38:19.870 に答える
2

オプション 2 は、ドメインを最適にキャプチャする場合、おそらく最適なソリューションです。その場合、新しいタイプは論理エンティティを表すため、他の多くの場所で使用されます。

于 2011-03-10T21:23:43.583 に答える
1

それは、IntersectResult の概念の一貫性に完全に依存します。

技術的には、どちらかを優先する理由はありません。

于 2011-03-10T21:22:19.863 に答える