web-dev-qa-db-ja.com

拡張メソッドと静的クラスメソッド

Visual Studio C#プロジェクトに参加しました。以前の同僚は、用途に応じて複数のファイルに対して静的クラスで多くの拡張メソッドを使用していました。

以前の経験では、Extensionメソッドを使用する場合はより選択的でしたが、代わりに静的クラスでpublic staticメソッドを使用しました。

どちらが優れているのか、それとも本当に気付かないフレーバーや業界標準になっているのか、と思いました。

おかげで、

2

拡張方法はもっと「発見可能」だと思います。特定のタイプがある場合、Intelli-senseは自動的に拡張メソッドを提供します。

静的クラスと静的メソッドの場合、参照できるように静的クラスの名前を知っている必要があります。小さなプロジェクトでは、これは違いをもたらさないかもしれませんが、いくつかのディレクトリと多くの異なるファイルを含むこの大きなプロジェクトでは、拡張メソッドは新しい人が見つけて使用する方が簡単かもしれません。

8
Jon Raynor

拡張メソッドと静的クラスのどちらを使用するかについては、業界標準はありません。正直なところ、静的クラスでは「拡張メソッド」areです。これは、C#の言語デザイナーがケーキを持って食べられるようにするケースです。

従来の「utils」静的クラスがあるとします。

_public static class AppUtils
{
    public static string ToStandardDateFormat(DateTime date)
    {
        // ... logic to format dates application-wide
    }
}
_

そう悪くはない。かみそりテンプレートの束に@AppUtils.ToStandardDateFormat(someDate)が表示されます。ほとんどの技術スタックのアプリケーションでかなり標準的な料金です。 5文字のコードを追加すると、次の両方を実行できます。

_public static class AppUtils
{
    public static string ToStandardDateFormat(this DateTime date)
    {
        // ... logic to format dates application-wide
    }
}
_

今、あなたはどちらかを行うことができます:

_@AppUtils.ToStandardDateFormat(someDate)
@someDate.ToStandardDateFormat()
_

ガイドラインはありません。標準なし。多くの場合、コインを裏返します。表か裏か、コーディングに戻ります。

5
Greg Burghardt

extension methodsの大きなメリットは、.Net Frameworkまたはサードパーティのクラスに、ソースコードがない、または変更できない追加機能を追加できることです。

例えば

public static class MyStringExtender
{
    /// <summary>
    /// Convert a string to a byte array using Ascii encoding
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static byte[] AsciiToByteArray(this string source)
    {
        return string.IsNullOrEmpty(source)
                   ? new byte[0]
                   : new ASCIIEncoding().GetBytes(source);
    }
}
4
Peregrine

私にとっての最大の利点は、読みやすさです。

メソッドチェーンを使用する一般的なLINQステートメントについて少し考えてみましょう。

_var total = myList.Where(x => x.num > 5)
                  .Select(x => x.num)
                  .Distinct()
                  .Aggregate((total, next) => total + next);
_

かなり読みやすい。しかし、静的メソッドを使用して同じことを行うことができます。

_var total = Enumerable.Aggregate(Enumerable.Distinct(Enumerable.Select(Enumerable.Where(myList, x => x.num > 5), x.num)), (total, next) => total + next);
_

そして、少しフォーマットしても、

_var total = Enumerable.Aggregate(
                Enumerable.Distinct(
                    Enumerable.Select(
                        Enumerable.Where(myList, x => x.num > 5)
                       , x.num)
                    )
               , (total, next) => total + next);
_

まだ読みにくいです。ラムダは、それらが使用する関数名から非常に離れています。それを解きほぐして、何が実際に起こっているのかを理解するのはかなり難しくなります。メソッドチェーンバージョンは(少なくとも私にとっては)はるかに読みやすくなっています。

コードを最も読みやすく、使いやすくするものを選びます。操作がほとんどまたは任意のコンテキストのオブジェクトに適用できる場合は、拡張メソッド(変換、フォーマットなど)を使用します。特定のコンテキストでのみ適用可能な場合は、静的メソッド(InterestCalculator.CalculateInterest(decimal principle, decimal interestRatePerMonth, int numberOfMonths)は、10進数または整数の拡張メソッドとしては不十分です。

4
Becuzz