web-dev-qa-db-ja.com

拡張メソッドと静的ユーティリティクラス

C#アプリで静的ユーティリティクラスに対して拡張メソッドを使用することの長所と短所を探しています。

たとえば、拡張メソッド列のプラスは、「StringUtils」のようなものではなく、クラス名で呼び出すと便利です。しかし、デメリットは、フレームワークにあるものとないものの間の境界線を曖昧にする可能性があるということです。

40
AJM

proは、フレームワークにあるものとないものの間の境界線を曖昧にすることです。独自のコードを自然に使用できます。フレームワークコードとして、フレームワークタイプで動作します。

もちろん、拡張メソッドを任意に使用するべきではありません-all静的メソッドが拡張メソッドになるべきではありません。

私はそれを、メソッドが最初のパラメーターを論理的に「操作」しているかどうかと考えようとしています。インスタンスメソッドとして含めることができた場合、インスタンスメソッドとして意味がありますか?

あなたが気付いていないかもしれない「詐欺」:拡張型が後で同じパラメータで適用可能な同じ名前のインスタンスメソッドを追加した場合、呼び出しコードは次に再コンパイルするときにそのインスタンスメソッドの呼び出しを透過的に開始します。たとえば、Streamは.NET4で CopyTo を取得しました...以前にCopyTo拡張メソッドを作成しましたが、作成しませんでした呼ばれる。これが発生しているという警告はないので、警戒する必要があります。

1つの注意点:拡張方法は、ベストプラクティスが実際に確立されるのに十分なほど長く存在していません。あなたはすべての意見(私自身の意見でさえ-あるいはおそらく特に-)を注意深く検討する必要があります。

51
Jon Skeet

結局のところ、どちらのアプローチも静的メソッドを使用します。の唯一の違い

string foo = "bob";
StringUtils.DoSomething(foo);

そして

string foo = "bob";
foo.DoSomething();

シンタックスシュガーです。それは、個人的な好みとコーディング標準に要約されます。メソッド名は、静的クラス名を表示する必要がないほど説明的である場合があります。また、クラス名を含める方が理にかなっている場合もあります。

最後に、拡張メソッドは静的メソッドとしても呼び出すことができます!

string foo = "bob";
StringExtensions.DoSomething(foo);

上記は2番目の例と同じコードを使用していますが、呼び出し方が異なります。この最後の一口を念頭に置いて、拡張メソッドとして静的ユーティリティクラスを実際に作成し、必要に応じてそれらを呼び出すことができます。

12
Doctor Blue

私は個人的に、Extensionメソッドによって提供される可読性とチェーン呼び出し(暗黙的に可読性を提供します)が好きです。

 1) Readability:  
     bool empty = String.IsNullOrEmpty (myString)
     //in comparison to
     bool empty = myString.IsNullOrEmpty ();

 2) Chain calls:  
    var query = Enumerable.Range(0, 10)
                         .Where(x => x % 2 == 0)
                         .Reverse();
    //instead of
    var query = Enumerable.Reverse(Enumerable.Where(Enumerable.Range(0, 10), x => x % 2 == 0));

Conは、誤って拡張メソッドを実行した場合に、インスタンスメンバーによってオーバーライドされる可能性があることです。個人的に私はこれが好きではありません。同じアセンブリで発生している場合は、少なくともコンパイラが叫んでいるはずです。

5
Srikanth