9

私は最近、拡張メソッドを使用して、自分が制御する (つまり、同じプログラム内にあり、変更できる) クラスにヘルパー ユーティリティを実装するというアイデアをいじっています。その背後にある理論的根拠は、多くの場合、これらのヘルパー ユーティリティは非常に特殊なシナリオで使用され、クラスの内部値へのアクセスを必要としないということです。

たとえば、StackExchange クラスがあるとします。PostQuestionandSearchとのようなメソッドがありAnswerQuestionます。

では、StackOverflow にだまされないように、レピュテーションを手動で計算したい場合はどうすればよいでしょうか。次の行に沿って何かを実装します。

int rep=0;
foreach(var post in StackExchangeInstance.MyPosts)
{
  rep+=post.RepEarned;
}

StackExchange クラスにメソッドを追加することもできますが、内部処理は必要なく、プログラムの他の 1 つまたは 2 つの部分からのみ使用されます。

代わりに、これらの特定のヘルパー メソッドが 10 個または 20 個あると想像してください。確かに特定のシナリオでは便利ですが、一般的なケースでは間違いありません。私の考えは、次のようなものを変更しています

public static RepCalcHelpers
{
  public static int CalcRep(StackExchange inst){ ... }
}

のようなものに

namespace Mynamespace.Extensions.RepCalculations
{
  public static RepCalcExtensions
  {
    public static int CalcRep(this Stackexchange inst){...}
  }
}

名前空間に注意してください。これを使用して、特定のシナリオ内で拡張メソッドをグループ化するのが理想的です。たとえば、「RepCalculations」、「Statistics」などです。

このタイプのパターンを聞いたことがあるかどうかを調べてみましたが、変更できないクラス以外に拡張メソッドが使用されているという証拠は見つかりませんでした。

この「パターン」にはどのような欠点がありますか? 代わりに、継承または構成、またはこれのための古き良き静的ヘルパークラスに固執する必要がありますか?

4

4 に答える 4

4

拡張メソッドに関するフレームワーク設計ガイドラインのセクションを読みます。これは、第 2 版の著者の 1 人による投稿です。あなたが説明しているユース ケース (特殊なヘルパー メソッド) は、Phil Haack によって拡張メソッドの有効な用途として引用されていますが、これらの「隠された」メソッドを見つけるには API に関する追加の知識が必要であるという欠点があります。

その投稿では言及されていませんが、本の中で推奨されているのは、拡張メソッドが拡張クラスとは別の名前空間に入るということです。そうしないと、常に IntelliSense で表示され、オフにする方法がありません。

于 2012-12-28T17:05:22.093 に答える
0

拡張メソッドは、クラスでインターフェイスを実装し、同じインターフェイスを実装する他の「将来の」クラスで同じメソッドを実装する必要がないようにしたい場合に非常に役立ちます。たとえば、StackExchange は IStackExchange を実装し、ProgrammersExchange も IStackExchange を実装します。サンプルの拡張メソッドは、CalcRep を 1 回だけ実装し、両方のクラスで再実装する必要がない場合に役立ちます。これがまさに、静的 Enumerable クラスに存在するすべての拡張メソッドの理由です。

これ以外に、既に変更可能なクラスで拡張メソッドを使用する説得力のある理由は見当たりません。どちらかといえば、過負荷解決プロセスの後半で考慮されるという欠点があります。

于 2012-12-28T17:20:46.793 に答える
0

このパターンはどこかで見たことがあると思います。非常に混乱する可能性がありますが、非常に強力でもあります。そうすれば、ライブラリ内のクラスと、別の名前空間内の一連の拡張メソッドを提供できます。次に、ライブラリを使用している人は誰でも、拡張メソッドを使用して名前空間をインポートするか、独自の拡張メソッドを提供するかを選択できます。

このパターンの適切な候補は、単体テストのみに使用されるいくつかの拡張メソッドがある場合です (たとえば、単体テストのみに必要な意味で 2 つのオブジェクトが等しいかどうかを比較する場合)。

于 2012-12-28T17:14:58.937 に答える
0

拡張メソッドがパブリック インスタンス メソッドと同等であるという比較を行っているようです。それは本当にそうではありません。

拡張メソッドは、呼び出されるためのより便利な構文を持つパブリックな静的ユーティリティ メソッドです。

したがって、まず、このメソッドがクラス自体のインスタンス メソッドであることが適切か、それとも外部クラスの静的メソッドであることがより適切であるかを自問する必要があります。この機能は高度にローカライズされており、クラス自体が実行する動作ではなく、外部エンティティによってクラスで実行される動作であるため、この機能を必要とするクラスのユーザーはほとんどいないという事実は、静的であることが適切であることを意味します。主な欠点は、誰かが担当者を持っていてUser、担当者を再計算したい場合、その動作を見つけるのが潜在的に困難になることです。さて、この特定のケースでは、それは少しフェンスの上にあり、別の方法に進むこともできますが、私は静的メソッドに傾いています.

静的にする必要があると判断したので、それが拡張メソッドであるべきかどうかはまったく別の問題です。これははるかに主観的であり、個人的な好みの領域に入ります。メソッドは連鎖する可能性がありますか? その場合、拡張メソッドは、静的メソッドへのネストされた呼び出しよりもはるかにうまく連鎖します。それを使用するファイルで多く使用される可能性がありますか? もしそうなら、拡張メソッドはおそらくコードを少し単純化するでしょう。おもちゃの例では、私はおそらく個人的にはそうしないと言うでしょうが、そうする人にはまったく問題はありません(結局のところ、拡張メソッドを通常のパブリック静的メソッドの構文であるかのように使用できます) )。おもちゃではない例については、ほとんどの場合、ケースバイケースの決定です。

拡張メソッドがインスタンス化されたメソッドよりも強力なエッジ ケースがいくつかあることにも言及する価値があります。特に、型推論の利用を通じて。通常のインスタンス メソッドを使用すると、型またはその型のサブタイプを受け入れるのは簡単ですが、親の型の代わりに渡された型を返すと便利な場合があります。これは特に流暢な API で使用されます。ただし、これはあまり一般的な例ではなく、質問とは大まかに関連しているだけなので、詳しく説明しません。

于 2012-12-28T17:15:10.913 に答える