2011-09-22 1 views
5

すでにいくつかのプロパティ値が設定されているウィジェットを用意する必要があります。私はウィジェットの名前を変更する必要があります。私はオプション3に向けて描かれていますが、私はなぜその理由を明確に説明していません。C#の引数を変更して返すのに最適ですか?

public void Do(Widget widget) { // 1 
    widget.Name = "new name"; 
} 

public void Do(ref Widget widget) { // 2 
    widget.Name = "new name"; 
} 

public Widget Do(Widget widget) { // 3 
    widget.Name = "new name"; 
    return widget; 
} 

私はいくつかの質問に悪魔の支持者を遊ぶのが好きと回答を集め、私はオプション3

オプション1に描かれていますなぜ私が説明するためにしたい:ちょうどなぜない渡されたウィジェットを変更しますか?あなたは1つのオブジェクトを "返す"だけです。渡されたオブジェクトを使用するだけではどうですか?

オプション2:なぜでないか返品無効ですか?なぜ、パラメータオブジェクト自体への実際のメモリポインタを使用しているというシグネチャで通信するだけではないのですか?

オプション3:あなたが渡しているのと同じオブジェクトを返すことはあなたにとって奇妙ではありませんか?

+0

これ以上の文脈がなければ、意見はほとんどありません。 – Cymen

+0

@Lance:各オプションについての質問、例、およびコメントの定式は、.NETで参照型がどのように動作するかについての混乱を示唆しています。例えば、2番目のオプションで 'ref'を使うのは完全に超過です。 – LBushkin

+1

@LBushkin合意。私の理解では、オプション2は、そのプロパティの1つではなく、「ウィジェット」に割り当てていればはるかに面白いですが、オプション2は、多くの開発者(おそらく私自身はおそらく時々含む) 'ref'キーワードを適切に使用しています。 – lance

答えて

12

オプション1:これは最も一般的なアプローチである - あなたが参照自体を変更したくない場合は、参照を必要としません。渡されたオブジェクトが実際に変更されていることを期待して、メソッドの名前を適切に指定してください。

オプション2:これは、あなたが新しいWidgetインスタンスを作成したり、既存のウィジェットを指すように参照を設定つまり、渡されたリファレンス自体を変更したい場合は、あなたがしたい場合は(これが役に立つかもしれないだけに有用ですそれらがすべて同じプロパティを持つ場合は全体の数を低く保ちます。Flyweight patternを参照してください。返されたウィジェットは、この場合は不変でなければなりません。あなたの場合、これは適切ではないようです。

オプション3:これは流暢「ビルダー」のアプローチを可能に - また、その利点、一部の人々は、より表現力と自己文書化を検討ウィジェットへの変更のすなわちチェーンを持っています。また、Fluent interface

+0

呼び出し元は指定しませんが、ウィジェットが構造体である可能性があります。この場合、オプション2と3だけが意味をなさないでしょう。 – LBushkin

+0

@LBushkin:それは確かに本当です - 私はそれが非常に起こりそうもないと思います。もしそうなら、おそらく他の問題があります。 – BrokenGlass

+0

@BrokenGlass渡されたオブジェクトが変更されるという予想を設定するために、どのような命名規則をお勧めしますか? – lance

4

実際には3つのオプションの間に機能的な違いはありません。 (あなたの質問に関連しているの違い、ちょうどなしがあります。)それをシンプルに保つ - useオプション1.

6

オプション1:

ファイン。まさに私が使うもの。ウィジェット自体の内容は変更することはできません。

オプション2:

いいえいいえいいえ。あなたは、参照自体を変更しないので、あなたはrefを使用する必要はありません。あなたが参照自体を変更した場合(たとえばwidget = new Widget()、次いでout/refは正しい選択ですが、私の経験ではほとんど必要だと

オプション3:オプション1と同様に
しかし、流暢に連鎖させることができます個人的には私はこれが好きではありません。コピーを返してオリジナルのオブジェクトをそのままにしておくと、その署名だけが使用されます。


しかし、ここで最も重要なことは、どのようにあなた名前方法。その名前は、元のオブジェクトが変異していることを明確に暗示する必要があります。

多くの場合、オプション4を選択します。タイプを不変にしてコピーを返します。しかし、明らかに実体であり価値がないウィジェットでは、これは意味をなさない。

+0

オプション1は、値渡しのためこの関数を呼び出すコードのウィジェットを変更しません、参照ではありません。 – David

+2

@Davidウィジェットが参照型の場合、ウィジェットの内容が変更されます。あなたが言っているのは、構造体/値型にのみ適用され、ウィジェットをC#で値型にする人は気違いです。 – CodesInChaos

+0

@David:**あなたのステートメントは 'Widget'が構造体**の場合にのみ真です。それが参照型であれば、 'Widget'インスタンスへの参照は値渡しされ、呼び出し側は' Do() 'メソッドで行われた変更を観察することができます。 – LBushkin

1

私はオプション1とオプション3の両方が実行可能なオプションだと思います。オプション3は、メソッドのウィジェットを変更していることを意味するという点で、自己文書化の利点があります。私は最悪のオプションはオプション2だと思う。refというキーワードは、あなたが最も確実にやっていないオブジェクトの参照を変更していることを意味する。

+1

オプション3は自己文書化として表示されません。ほとんどの場合、このシグネチャは、パラメータを変更せずに変更されたコピーを返すことを意味します。オプション3の利点は、チェーン化が可能だということですが、それは自己文書化が少ないと思います。 – CodesInChaos

+0

@CodeInChaos - 実際にはオプション1を使用していますが、オプション1でオブジェクトのプロパティが変わる可能性があることを理解しています。たとえば、 'public void Log(MyClass a) {a.IWasLogged = true; Logger.Log(a); } 'aはここで変更されましたが、開発者には分かりません。私はオプション3に行く価値はあるとは思っていませんが、その事実を強調したいと思います。 – skaz

関連する問題