拡張メソッドのどのような利点を見つけましたか?[閉まっている]


84

C#の「非信者」は、拡張メソッドの目的は何かと私に尋ねていました。特に、元のオブジェクトのソースを所有/制御していない場合は、すでに定義されているオブジェクトに新しいメソッドを追加できることを説明しました。

彼は「なぜあなた自身のクラスにメソッドを追加しないのですか?」と提起しました。私たちは(良い意味で)ぐるぐる回っています。私の一般的な反応は、それがツールベルトの別のツールであり、彼の反応はそれがツールの無駄な無駄であるということです...しかし、私はもっと「啓発された」答えが得られると思いました。

自分のクラスに追加されたメソッドを使用できなかった(または使用すべきではなかった)拡張メソッドを使用したシナリオは何ですか?


2
拡張メソッドをサポートするために人々が作成できる(そして作成した)確かに有効なポイントがあると思います...しかし、拡張メソッドの代わりに静的メソッドを「使用できなかった」シナリオは絶対にありません。拡張メソッドは実際に単なる静的メソッドであり、別の方法でアクセスされます。覚えておくべきことです。
ダン・タオ

@DanTaoは、簡単に言えば、拡張メソッドによる呼び出しをかけがえのないものにしているのは、名前そのものです。Extensions.To(1, 10)意味がなく、1.To(10)説明的です。もちろん、私はあなたが話している技術的な側面を理解しています。実際、静的メソッドの代わりに拡張アプローチを「使用できなかった」シナリオがありますdynamic。たとえば、リフレクションなどです。別のケースはです。
nawfal 2013

回答:


35

拡張メソッドは、コードを作成するときに非常に役立つと思います。基本型に拡張メソッドを追加すると、インテリセンスですばやく取得できます。

ファイルサイズフォーマットするためのフォーマットプロバイダーがあります。それを使用するには、私は書く必要があります:

Console.WriteLine(String.Format(new FileSizeFormatProvider(), "{0:fs}", fileSize));

私が書くことができる拡張メソッドの作成:

Console.WriteLine(fileSize.ToFileSize());

よりクリーンでシンプル。


4
拡張メソッドのよりわかりやすい名前を使用すると、さらにわかりやすくなります。例:fileSize.ToFormattedString();
David Alpert

1
MMM、ToFormattedFizeSize()多分、それは(ロングタイプのためToFormattedString拡張メソッドだが)説明的な名前ではありません
エドゥアルドCampañó

3
しかし、ポイントが作られました。fileSize.ToFileSize()を読むと、なぜ複製するのかと尋ねます。それは実際に何をしているのですか?これは単なる例ですが、わかりやすい名前を付けると、わかりやすくシンプルになります。
デビッドアルパート

1
あなたのしている右のテストと同じように、それは右の名前を選択することが非常に重要です
エドゥアルドCampañó

5
ただし、提供した例は拡張メソッドである必要はないため、これは実際には質問に直接答えるものではありません。あなたは持っていたかもしれませんLongToFileSize(fileSize)、それは同じように簡潔で、間違いなく同じように明確です。
ダン・タオ

83

拡張メソッドの唯一の利点は、コードの可読性です。それでおしまい。

拡張メソッドを使用すると、これを行うことができます。

foo.bar();

これの代わりに:

Util.bar(foo);

現在、C#にはこのようなものがたくさんあります。言い換えると、C#には些細なことのように見え、それ自体では大きなメリットがない多くの機能があります。ただし、これらの機能を組み合わせ始めると、その部分の合計よりも少し大きいものが表示されるようになります。LINQクエリは拡張メソッドなしではほとんど読み取れないため、LINQは拡張メソッドから大きな恩恵を受けます。LINQは拡張メソッドなしで可能ですが、実用的ではありません。

拡張メソッドは、C#の部分クラスによく似ています。それ自体はあまり役に立たず、些細なことのようです。しかし、生成されたコードを必要とするクラスで作業を開始すると、部分クラスの方がはるかに理にかなっています。


1
x.Foo(something).Bar(somethingelse).Baz(yetmoresomething)のような連鎖メソッドを使用している場合、これはさらに重要になります。これはIEnumerable <>拡張メソッドで最も一般的であり、読みやすさが大幅に向上します
ShuggyCoUk 2009年

2
私が得られないのは、foo.bar()がbar()がfooのメソッドであることを私に示唆しているということです。それで、それがうまくいかないとき、私は間違った場所を探すことになります。これが実際に私にとって読みやすさの向上であるかどうかはわかりません。
マーティンブラウン

3
VS IDEでbar()を右クリックし、[定義に移動]を選択すると、適切な場所に移動します。
ジェフマーティン

9
言語構造の98%の唯一の利点は、コードの可読性です。ブランチ演算子、ラベル、goto、インクリメントを超えたものはすべて、あなたの生活を少し楽にするためにあります。
ジョバンニガルボ

2
それは完全に真実ではありません。拡張メソッドがクラスを拡張する唯一の方法である場合があります。封印されたクラスに加えて、私はかなりユニークな状況でそれらを使用します。以下の私の投稿を参照してください。
エドウィンジャービス

34

ツーリングを忘れないでください!タイプFooに拡張メソッドMを追加すると、Fooのインテリセンスリストに「M」が表示されます(拡張クラスがスコープ内にあると想定)。これにより、MyClass.M(Foo、...)よりも「M」を簡単に見つけることができます。

結局のところ、それは他の場所(静的メソッド)の単なる構文糖衣ですが、家を買うようなものです:「場所、場所、場所!」タイプに掛かっていれば、人々はそれを見つけるでしょう!


2
これにわずかな負のもあります。このように長いリストとのIntelliSenseオートコンプリート、アップSystem.Linqのフィルからのものとして拡張メソッドは、(ナビゲートするために少し難しくなっています。
ジャレドアップダイク

@Jared:...ただし、拡張メソッドが存在する名前空間をインポートした場合にのみ、この「IntelliSense汚染」を実際にある程度制御できます。次に、BCLにStringはインスタンスメソッドのかなり長いリストが付属するクラス(など)があることを忘れないでください。したがって、この問題は拡張メソッドに固有のものではありません。
stakx -もはや寄与しない

29

私が遭遇した拡張メソッドのさらに2つの利点:

  • 流暢なインターフェイスは、拡張メソッドの静的クラスにカプセル化できるため、コアクラスとその流暢な拡張の間の関心の分離を実現できます。これにより、保守性が向上することを確認しました。
  • 拡張メソッドはインターフェイスから切り離すことができるため、コントラクト(インターフェイスを介して)および関連する一連のインターフェイスベースの動作(拡張メソッドを介して)を指定でき、関心の分離を提供します。例は、のようにLINQの拡張メソッドであるSelect(...)Where(...)等、オフホンIEnumerable<T>インターフェース。

1
両方のポイントのコード例を引用して、理解を深めてください。それは興味深い視点のようです。
RBT 2016年

ええ、2番目のポイントの例がいいでしょう。
ini 2017

26

拡張メソッドの最良の使用法のいくつかは、次の機能です。

  1. サードパーティのオブジェクト(商用または社内のオブジェクトであるが、別のグループによって管理されている)の機能を拡張します。これは、多くの場合、としてマークされsealedます。
  2. 抽象クラスを実装せずにインターフェイスのデフォルト機能を作成する

たとえば、IEnumerable<T>。拡張メソッドは豊富ですが、汎用のForEachメソッドを実装していないのは面倒です。だから、私は自分で作りました:

public void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    foreach ( var o in enumerable )
    {
        action(o);
    }
}

出来上がり、IEnumerable<T>実装タイプに関係なくすべてのオブジェクト、そして私がそれを書いたかどうか、または他の誰かがForEach私のコードに適切な「using」ステートメントを追加することによるメソッドを持っていました。


3
+1私はこの拡張機能が大好きで、同じように作成しました。とても便利
マズロー

10
メソッドは静的である必要があることに注意してください。この拡張機能の使用を決定する前に、blogs.msdn.com / ericlippert / archive / 2009/05/18 /…を読むことをお勧めします。
TrueWill 2010年

IEnumerableにForEach拡張メソッドを実装することが評価されない理由-blogs.msdn.microsoft.com/ericlippert/2009/05/18/…–
RBT

12

拡張メソッドを使用する大きな理由の1つは、LINQです。拡張メソッドがないと、LINQでできることの多くは非常に困難になります。Where()、Contains()、Select拡張メソッドは、構造を変更せずに既存の型にさらに多くの機能が追加されることを意味します。


4
それは「の1つ」ではなく、拡張メソッドの理由です。
gbjbaanb 2010

3
どうして?これは、唯一の要件ではなく、拡張メソッドを使用する多くの理由の1つです。LINQを使用せずに拡張メソッドを使用できます。
Ray Booysen 2010

彼はそれが彼らが作られた理由だと思ったと思いますが、そうです、彼は彼らが彼らの唯一の適切な使用法であるように聞こえさせます。
ブレントリッテンハウス

9

拡張メソッドの利点についてはたくさんの答えがあります。不利な点に対処するのはどうですか?

最大の欠点は、同じコンテキストで同じシグネチャを持つ通常のメソッドと拡張メソッドがある場合、コンパイラエラーや警告が発生しないことです。

特定のクラスに適用する拡張メソッドを作成するとします。その後、誰かがそのクラス自体に同じシグネチャを持つメソッドを作成します。

コードがコンパイルされ、ランタイムエラーが発生しない場合もあります。 ただし、以前と同じコードを実行しているわけではありません。


1
4.所有していないタイプを拡張する前によく考えてください。所有している型の拡張メソッドのみを作成する場合は、拡張される型の変更によって拡張が壊れることを心配する必要はありません。一方、あなたが他の人々のタイプを拡張している場合、あなたは本質的に彼らの慈悲にあります。
DavidRR 2014年

1
...または、他の人が使用する可能性が低い名前を選択するか、定義する拡張メソッドの総数を最小化する(つまり、表面積を減らす)ことで、このリスクを最小限に抑えることができます。これを行うための1つの手法は、基になるオブジェクトをユーザーが制御する別の型に変換する1つの拡張メソッドを作成することです。
DavidRR 2014年

拡張メソッド(C#プログラミングガイド):一般に、独自の拡張メソッドを実装するよりもはるかに頻繁に拡張メソッドを呼び出すことになります。
DavidRR 2014年


4

拡張メソッドについての私の個人的な議論は、それらはOOP設計に非常によく適合するということです:単純なメソッドを検討してください

bool empty = String.IsNullOrEmpty (myString)

と比較して

bool empty = myString.IsNullOrEmpty ();

あなたの例がOOPと何の関係があるのか​​わかりません。どういう意味ですか?
Andrew Hare

1
メソッドがオブジェクトに属しているようです
Bluenuance 2009年

3
これは悪い例です(NullReferenceExceptionをスローする可能性があります)が、彼は正しい方向に進んでいます。より良い例は、Math.abs(-4)を-4.abs()のようなものに置き換えることです。
アウトロープログラマー

15
私の知る限り(そして私の経験では、メモリが役立つ場合)、拡張メソッドは起動するためにオブジェクトインスタンスを必要としないため、myString.IsNullOrEmpty()はNullReferenceExceptionをスローする必要はありません。
David Alpert

1
私は個人的に、nullインスタンスで動作することを目的とした拡張メソッドのファンではありません。読者には1つのことのように見えますが、別のことを行います。
マークシンプソン

4

拡張メソッドで何ができるかについては、上記のすばらしい答えが山ほどあります。

私の簡単な答えは-彼らは工場の必要性をほとんど排除します。

それらは新しい概念ではなく、それらの最大の検証の1つは、Objective-C(カテゴリ)のキラー機能であるということを指摘しておきます。それらはフレームワークベースの開発に非常に多くの柔軟性を追加するため、NeXTはNSAとウォール街の財務モデラーを主要なユーザーとして持っていました。

REALbasicはそれらをextendsメソッドとしても実装しており、開発を簡素化するために同様に使用されています。


4

拡張メソッドの背後にある重要な理由としてコードの可読性の向上に言及している他の回答をここでサポートしたいと思います。これについては、メソッドチェーンとネストされたメソッド呼び出しの2つの側面と、意味のない静的クラス名を使用したLINQクエリの乱雑さについて説明します。


このLINQクエリを例として取り上げましょう。

numbers.Where(x => x > 0).Select(x => -x)

WhereSelectはどちらも拡張メソッドであり、静的クラスで定義されていますEnumerable。したがって、拡張メソッドが存在せず、これらが通常の静的メソッドである場合、コードの最後の行は基本的に次のようになります。

Enumerable.Select(Enumerable.Where(numbers, x => x > 0), x => -x)

そのクエリがどれだけ厄介になったのかを確認してください。


次に、独自のクエリ演算子を導入したい場合、フレームワーク内にあり、そのクラスを制御できないEnumerableため、他のすべての標準クエリ演算子のように、静的クラス内でそれを定義する方法は当然ありませんEnumerable。したがって、拡張メソッドを含む独自の静的クラスを定義する必要があります。次に、次のようなクエリが表示される場合があります。

Enumerable.Select(MyEnumerableExtensions.RemoveNegativeNumbers(numbers), x => -x)
//                ^^^^^^^^^^^^^^^^^^^^^^
//                different class name that has zero informational value
//                and, as with 'Enumerable.xxxxxx', only obstructs the
//                query's actual meaning.

3

(extension)メソッドをクラスに直接追加できるのは事実です。しかし、すべてのクラスがあなたによって書かれているわけではありません。コアライブラリまたはサードパーティライブラリのクラスは閉じられていることが多く、拡張メソッドなしでシンタティックシュガーを取得することは不可能です。ただし、拡張メソッドは、たとえばの(静的)スタンドアロンメソッドと同じです。c ++


3

拡張メソッドは、クラスとクラスの依存関係をクリーンに保つのにも役立ちます。たとえば、Fooが使用されるすべての場所でFooクラスのBar()メソッドが必要になる場合があります。ただし、別のアセンブリでそのアセンブリに対してのみ.ToXml()メソッドが必要になる場合があります。その場合、元のアセンブリではなく、そのアセンブリに必要なSystem.XmlまたはSystem.Xml.Linqの依存関係を追加できます。

利点:定義するクラスアセンブリの依存関係が必要最小限に抑えられ、他の消費アセンブリがToXml()メソッドを使用できなくなります。詳細については、このPDCプレゼンテーションを参照してください。


3

拡張メソッドがコードの可読性を向上させることに同意しますが、それは実際には静的ヘルパーメソッドに他なりません。

クラスに動作を追加するために拡張メソッドを使用するIMOは、次のようになります。

紛らわしい:プログラマーは、メソッドが拡張型の一部であると信じている可能性があるため、拡張名前空間がインポートされないときにメソッドが失われる理由を理解していません。

アンチパターン:拡張メソッドを使用してフレームワークの型に動作を追加し、それらを単体テストに送る人に出荷することにしました。現在、彼は偽造できない一連のメソッドを含むフレームワークに固執しています。


開発者が偽造できない一連のメソッドで立ち往生しているというのは真実ではありません。これらの拡張メソッドは、最終的に、拡張しているクラス/インターフェイスで何らかのメソッドを呼び出します。このメソッドは、仮想である場合にインターセプトできます。
パトリックHägne

1
さて、それは拡張メソッドで何が行われるかに依存します。提供された拡張メソッドをインターフェースで使用しているとしましょう。それらが拡張メソッドであるとは知らないのです。次に、インターフェイスへのメソッド呼び出しを偽造したくはありませんが、実際には静的メソッドを呼び出していることに気付きます。静的メソッド呼び出しは、プロキシベースの偽造APIによってインターセプトできないため、唯一のオプションは、拡張メソッドを反映して、実際に偽造するメソッドを見つけることです。ユニットテストIMOと組み合わせた場合でもアンチパターン。
HaraldV 2011年

2

拡張メソッドは、実際には、Martin Fowler's Bookの「IntroduceForeignMethod」リファクタリング(メソッドシグネチャに至るまで)を.NETに組み込んだものです。それらには基本的に同じ利点と落とし穴があります。このリファクタリングのセクションで、彼は、実際にメソッドを所有する必要があるクラスを変更できない場合の回避策であると述べています。


2
+1ですが、インターフェースで拡張メソッドを使用することもできることに注意してください。
TrueWill 2010年

2

私は主に、拡張メソッドを、おそらく無料の関数を禁止すべきではなかったという承認として見ています。

C ++コミュニティでは、メンバーよりも無料の非メンバー関数を優先することは、多くの場合、優れたOOPプラクティスと見なされます。これらの関数は、不要なプライベートメンバーにアクセスすることによってカプセル化を壊さないためです。拡張メソッドは、同じことを実現するための迂回方法のようです。つまり、プライベートメンバーにアクセスできない静的関数のよりクリーンな構文です。

拡張メソッドはシンタックスシュガーにすぎませんが、それらを使用しても害はありません。


2
  • 醜いユーティリティ関数を呼び出す代わりに、オブジェクト自体のIntellisense
  • 変換関数の場合、「XToY(X x)」を「ToY(this X x)」に変更できます。これにより、醜いXToY(x)ではなくかなりのx.ToY()になります。
  • 制御できないクラスを拡張する
  • クラス自体にメソッドを追加することが望ましくない場合は、クラスの機能を拡張します。たとえば、ビジネスオブジェクトをシンプルでロジックフリーに保ち、拡張メソッドに醜い依存関係を持つ特定のビジネスロジックを追加できます。

2

それらを使用して、オブジェクトモデルクラスを再利用します。データベースにあるオブジェクトを表すクラスがたくさんあります。これらのクラスはクライアント側でオブジェクトを表示するためにのみ使用されるため、基本的な使用法はプロパティへのアクセスです。

public class Stock {
   public Code { get; private set; }
   public Name { get; private set; }
}

その使用パターンのために、これらのクラスにビジネスロジックメソッドを含めたくないので、すべてのビジネスロジックを拡張メソッドにします。

public static class StockExtender {
    public static List <Quote> GetQuotesByDate(this Stock s, DateTime date)
    {...}
}

このようにして、不要なコードでクライアント側に過負荷をかけることなく、ビジネスロジック処理とユーザーインターフェイスの表示に同じクラスを使用できます。

このソリューションの興味深い点の1つは、オブジェクトモデルクラスがMono.Cecilを使用して動的に生成されるため、必要な場合でもビジネスロジックメソッドを追加するのが非常に難しいことです。XML定義ファイルを読み取り、データベースにあるオブジェクトを表すこれらのスタブクラスを生成するコンパイラがあります。この場合の唯一のアプローチは、それらを拡張することです。


1
あなたは...このため、部分的なクラスを使用することができます
JJoos


1

前回のプロジェクトでは、拡張メソッドを使用してValidate()メソッドをビジネスオブジェクトにアタッチしました。シリアル化可能なデータがオブジェクトを転送し、製品、顧客、商人などの一般的なeコマースエンティティが異なるドメインで使用されるビジネスオブジェクトがあるため、これを正当化しました。異なるドメインでは、ビジネスルールも異なる可能性があるため、カプセル化しました。データ転送オブジェクトの基本クラスに関連付けられたValidateメソッドのレイトバウンド検証ロジック。これが理にかなっていることを願っています:)


1

拡張メソッドが非常に役立つ1つのケースは、ASMXWebサービスを使用するクライアントアプリケーションでした。シリアル化のため、Webメソッドの戻り値の型にはメソッドが含まれていません(これらの型のパブリックプロパティのみがクライアントで使用できます)。

拡張メソッドを使用すると、クライアント側でさらに別のオブジェクトモデルや多数のラッパークラスを作成しなくても、Webメソッドによって返される型に(クライアント側で)機能を追加できます。



1

また、拡張メソッドは、C#スタイルで使用したときに、Linqクエリを読みやすくする方法として追加されたことを忘れないでください。

これらの2つの影響は完全に同等ですが、最初の影響ははるかに読みやすくなります(もちろん、連鎖するメソッドが増えると、読みやすさのギャップが大きくなります)。

int n1 = new List<int> {1,2,3}.Where(i => i % 2 != 0).Last();

int n2 = Enumerable.Last(Enumerable.Where(new List<int> {1,2,3}, i => i % 2 != 0));

完全修飾構文は次のようにする必要があることに注意してください。

int n1 = new List<int> {1,2,3}.Where<int>(i => i % 2 != 0).Last<int>();

int n2 = Enumerable.Last<int>(Enumerable.Where<int>(new List<int> {1,2,3}, i => i % 2 != 0));

偶然にも、との型パラメーターはWhereLastこれら2つのメソッドの最初のパラメーター(キーワードによって導入され、thisそれらを拡張メソッドにするパラメーター)の存在のおかげで推測できるため、明示的に言及する必要はありません。

この点は明らかに(とりわけ)拡張メソッドの利点であり、メソッドチェーンが含まれるすべての同様のシナリオでこの点を利用できます。

特に、基本クラスのメソッドを任意のサブクラスで呼び出して、このサブクラスへの強く型付けされた参照を返すことがわかった、よりエレガントで説得力のある方法です(サブクラスタイプを使用)。

例(わかりました、このシナリオは完全に安っぽいです):おやすみの後、動物は目を開けて泣きます。すべての動物は同じように目を開きますが、犬は吠え、アヒルは鳴きます。

public abstract class Animal
{
    //some code common to all animals
}

public static class AnimalExtension
{
    public static TAnimal OpenTheEyes<TAnimal>(this TAnimal animal) where TAnimal : Animal
    {
        //Some code to flutter one's eyelashes and then open wide
        return animal; //returning a self reference to allow method chaining
    }
}

public class Dog : Animal
{
    public void Bark() { /* ... */ }
}

public class Duck : Animal
{
    public void Kwak() { /* ... */ }
}

class Program
{
    static void Main(string[] args)
    {
        Dog Goofy = new Dog();
        Duck Donald = new Duck();
        Goofy.OpenTheEyes().Bark(); //*1
        Donald.OpenTheEyes().Kwak(); //*2
    }
}

概念的にOpenTheEyesAnimalメソッドである必要がありますが、抽象クラスのインスタンスを返しますAnimal。これは、BarkまたはDuckなどの特定のサブクラスメソッドを認識していません。* 1および* 2としてコメントされた2行は、コンパイルエラーを発生させます。

しかし、拡張メソッドのおかげで、一種の「呼び出されるサブクラスタイプを知っているベースメソッド」を持つことができます。

単純なジェネリックメソッドがその仕事をすることができたかもしれないが、はるかに厄介な方法であることに注意してください:

public abstract class Animal
{
    //some code common to all animals

    public TAnimal OpenTheEyes<TAnimal>() where TAnimal : Animal
    {
        //Some code to flutter one's eyelashes and then open wide
        return (TAnimal)this; //returning a self reference to allow method chaining
    }
}

今回は、パラメーターがないため、戻り型の推論はできません。呼び出しは他の何物でもありえません:

Goofy.OpenTheEyes<Dog>().Bark();
Donald.OpenTheEyes<Duck>().Kwak();

...より多くの連鎖が含まれる場合、コードの重みが大きくなる可能性があります(特に、typeパラメーターが常に<Dog>Goofyの行と<Duck>Donaldの行にあることを知っています...)


1
初めて「クワク」を見た。これは他の国で一般的なスペルですか?私が今までにそれが綴られているのを見た唯一の方法は「いんちき」です。
ブレントリッテンハウス2017年

0

私はそれについて一言だけ言います:保守性これは拡張メソッドが使用するための鍵です


4
これが何を意味するのかわからないので、複数の単語が必要になるかもしれません。
アウトロープログラマー

2
私は実際、それは拡張メソッドに反対する議論だと思います。拡張方法のリスクの1つは、すべての人が作成して、どこにでも配置できることです。注意深く使用しないと、野生の成長が起こる可能性があります。
Boris Callens

EMを使用している場合は、すべての参照を簡単に見つけることができます。また、1つの方法をグローバルに変更するには、1つの場所からのみ変更できます
Tamir

0

拡張メソッドは、より明確なコードを書くのに役立つと思います。

友人が提案したように、クラス内に新しいメソッドを配置する代わりに、ExtensionMethods名前空間に配置します。このようにして、クラスの論理的な秩序感を維持します。クラスを実際に直接処理しないメソッドは、クラスを乱雑にすることはありません。

拡張メソッドを使用すると、コードがより明確になり、より適切に整理されると思います。


0

これにより、エディター/ IDEがスマートにオートコンプリートの提案を行うことができます。


0

私はhtmlを構築するためにそれらが大好きです。多くの場合、繰り返し使用されるセクションや、関数が役立つが再帰的に生成されるセクションがありますが、そうしないとプログラムのフローが中断されます。

        HTML_Out.Append("<ul>");
        foreach (var i in items)
            if (i.Description != "")
            {
                HTML_Out.Append("<li>")
                    .AppendAnchor(new string[]{ urlRoot, i.Description_Norm }, i.Description)
                    .Append("<div>")
                    .AppendImage(iconDir, i.Icon, i.Description)
                    .Append(i.Categories.ToHTML(i.Description_Norm, urlRoot)).Append("</div></li>");
            }

        return HTML_Out.Append("</ul>").ToString();

オブジェクトがHTML出力用にカスタムロジックを準備する必要がある場合もあります。拡張メソッドを使用すると、クラス内でプレゼンテーションとロジックを混在させることなく、この機能を追加できます。


0

拡張メソッドは、ネストされた汎用引数を照合するのに役立つことがわかりました。

それは少し奇妙に聞こえますが、ジェネリッククラスMyGenericClass<TList>があり、TList自体がジェネリック(たとえばList<T>)であることがわかっているとすると、ネストされた「T」をリストから拡張せずに掘り出す方法はないと思いますメソッドまたは静的ヘルパーメソッド。静的ヘルパーメソッドしか使用できない場合、それは(a)醜く、(b)クラスに属する機能を外部の場所に移動することを余儀なくされます。

たとえば、タプル内の型を取得してメソッドシグネチャに変換するには、拡張メソッドを使用できます。

public class Tuple { }
public class Tuple<T0> : Tuple { }
public class Tuple<T0, T1> : Tuple<T0> { }

public class Caller<TTuple> where TTuple : Tuple { /* ... */ }

public static class CallerExtensions
{
     public static void Call<T0>(this Caller<Tuple<T0>> caller, T0 p0) { /* ... */ }

     public static void Call<T0, T1>(this Caller<Tuple<T0, T1>> caller, T0 p0, T1 p1) { /* ... */ }
}

new Caller<Tuple<int>>().Call(10);
new Caller<Tuple<string, int>>().Call("Hello", 10);

とはいえ、分割線がどこにあるべきかわかりません-メソッドはいつ拡張メソッドであり、いつ静的ヘルパーメソッドである必要がありますか?何かご意見は?


0

画面に入力ゾーンがあり、正確なタイプ(テキストボックス、チェックボックスなど)に関係なく、すべて標準の動作を実装する必要があります。各タイプの入力ゾーンはすでに特定のクラス(TextInputBoxなど)から派生しているため、共通の基本クラスを継承することはできません。

継承階層に上がることで、WebControlなどの共通の祖先を見つけることができたかもしれませんが、フレームワーククラスWebControlを開発しておらず、必要なものが公開されていません。

拡張メソッドを使用すると、次のことができます。

1)WebControlクラスを拡張し、すべての入力クラスで統一された標準の動作を取得します

2)または、すべてのクラスをインターフェイス(IInputZoneなど)から派生させ、このインターフェイスをメソッドで拡張します。これで、すべての入力ゾーンでインターフェイスに関連する拡張メソッドを呼び出すことができるようになります。入力ゾーンはすでに複数の基本クラスから派生しているため、このようにして一種の多重継承を実現しました。


0

拡張メソッドのすばらしい例はたくさんあります。特に上記のIEnumerablesにはそうです。

たとえば、IEnumerable<myObject>私が作成できる拡張メソッドを持っている場合IEnumerable<myObject>

mylist List<myObject>;

...リストを作成する

mylist.DisplayInMyWay();

拡張メソッドがないと、以下を呼び出す必要があります。

myDisplayMethod(myOldArray); // can create more nexted brackets.

もう1つの優れた例は、循環リンクリストをすばやく作成することです。

私はそれを信用することができます!

拡張メソッドを使用した循環リンクリスト

これらを組み合わせて、拡張メソッドを使用すると、コードは次のようになります。

myNode.NextOrFirst().DisplayInMyWay();

のではなく

DisplayInMyWay(NextOrFirst(myNode)).

拡張メソッドの使用それはよりすっきりと読みやすく、よりオブジェクト指向です。また、非常に近い:

myNode.Next.DoSomething()

それを同僚に見せてください!:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.