web-dev-qa-db-ja.com

C#拡張メソッドでクラスを拡張するにはどうすればよいですか?

拡張メソッドをクラスに適用できますか?

たとえば、DateTimeを拡張して、次のように呼び出すことができるTomorrow()メソッドを含めます。

DateTime.Tomorrow();

使えることを知っている

static DateTime Tomorrow(this Datetime value) { //... }

または

public static MyClass {
  public static Tomorrow() { //... }
}

同様の結果ですが、DateTime.Tomorrowを呼び出すことができるようにDateTimeを拡張するにはどうすればよいですか?

92
David Glenn

既存の型が部分としてマークされていない限り、既存の型にメソッドを追加することはできません。拡張メソッドを介して既存の型のメンバーになるappearのメソッドのみを追加できます。この場合、拡張メソッドはその型のインスタンスを使用するため、型自体に静的メソッドを追加することはできません。

次のような独自の静的ヘルパーメソッドの作成を妨げるものはありません。

static class DateTimeHelper
{
    public static DateTime Tomorrow
    {
        get { return DateTime.Now.AddDays(1); }
    }
}

次のように使用します:

DateTime tomorrow = DateTimeHelper.Tomorrow;
68
Andrew Hare

拡張メソッド を使用します。

例:

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
            return date.AddDays(1);
        }    
    }
}

使用法:

DateTime.Now.Tomorrow();

または

AnyObjectOfTypeDateTime.Tomorrow();
175
Kumu

拡張メソッドは、最初のパラメーターがT型のインスタンスである静的メソッドを、Tのインスタンスメソッドであるかのように見せる構文糖衣です。

そのため、「静的拡張メソッド」を作成する場合、拡張メソッドよりもコードのリーダーをさらに混乱させるので、メリットはほとんど失われます(完全に修飾されているように見えますが、実際にはそのクラスで定義されていないため)構文上の利益はありません(たとえば、Linq内で流callsなスタイルで呼び出しをチェーンできること)。

とにかく使用して拡張機能をスコープに入れる必要があるので、作成する方が簡単で安全であると主張します:

public static class DateTimeUtils
{
    public static DateTime Tomorrow { get { ... } }
}

そして、あなたのコードでこれを使用して:

WriteLine("{0}", DateTimeUtils.Tomorrow)
18
ShuggyCoUk

答えに最も近いのは、拡張メソッドをSystem.Typeオブジェクトに追加することです。きれいではないが、それでも面白い。

public static class Foo
{
    public static void Bar()
    {
        var now = DateTime.Now;
        var tomorrow = typeof(DateTime).Tomorrow();
    }

    public static DateTime Tomorrow(this System.Type type)
    {
        if (type == typeof(DateTime)) {
            return DateTime.Now.AddDays(1);
        } else {
            throw new InvalidOperationException();
        }
    }
}

それ以外の場合、IMO AndrewとShuggyCoUkの実装は改善されています。

9
Adrian Godong

型に変更を加えることなく新しいメソッドを追加することにより、既存の型を拡張する機能を提供します。インスタンスメソッド構文を使用して、アプリケーション内の拡張タイプのオブジェクトからメソッドを呼び出すことを「拡張」メソッドと呼びます。拡張メソッドは、型のインスタンスメンバーではありません。覚えておくべき重要な点は、静的メソッドとして定義されている拡張メソッドがスコープ内にあるのは、usingディレクティブを使用して名前空間がアプリケーションのソースコードに明示的にインポートされている場合のみです。拡張メソッドは静的メソッドとして定義されていますが、インスタンス構文を使用して呼び出されます。

ここで完全な例を確認してください http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

例:

class Extension
    {
        static void Main(string[] args)
        {
            string s = "sudhakar";
            Console.WriteLine(s.GetWordCount());
            Console.ReadLine();
        }

    }
    public static class MyMathExtension
    {

        public static int GetWordCount(this System.String mystring)
        {
            return mystring.Length;
        }
    }
3
sudhakar

クムと同じことをする

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
           return date.AddDays(1);
        }    
    }
}

しかし、この新しいDateTime()。Tomorrow();のように呼び出します。

DateTime.Now.Tomorrow();よりも多く見られると思います。

3
mimo

同様の何かを探していました-拡張メソッドを提供するクラスの制約のリスト。簡潔なリストを見つけるのは難しいようです。

  1. フィールドやメソッドなど、プライベートなものや保護されたものはありません。

  2. public static class...のように、静的クラスでなければなりません。

  3. クラスに含めることができるのはメソッドのみであり、それらはすべてパブリックスタティックである必要があります。

  4. 従来の静的メソッドを使用することはできません-this引数を含まないメソッドは許可されません。

  5. すべての方法を開始する必要があります。

    public static ReturnType MethodName(this ClassName _this、...)

したがって、最初の引数は常にthis参照です。

これが引き起こす暗黙の問題があります-何らかのロックを必要とするメソッドを追加する場合、クラスレベルでそれを実際に提供することはできません。通常、プライベートインスタンスレベルのロックを提供しますが、プライベートフィールドを追加することはできません。一部の外部クラスでパブリックスタティックとして提供するなど、非常に厄介なオプションが残されます。兆候 C#言語は、これらの設計にちょっとした悪循環がありました

回避策は、Extension Methodクラスを通常のクラスの単なるファサードとして使用することです。Extensionクラスのすべての静的メソッドは、おそらく a Singleton を使用して、実際のクラスを呼び出します。

3
Chris Moschini

残念ながら、それはできません。しかし、それは役立つと思います。次のように入力する方が自然です。

DateTime.Tomorrow

より:

DateTimeUtil.Tomorrow

Utilクラスでは、1つではなく2つの異なるクラスの静的メソッドの存在を確認する必要があります。

2
Meta-Knight

私たちは詳細な説明で答えを改善しました。今では、拡張メソッドについての理解がより簡単になりました

拡張メソッド :これは、サブクラス化を使用せずに既存のクラスの動作を拡張したり、元のクラスまたは構造体を変更または再コンパイルできるメカニズムです。

カスタムクラス、.netフレームワーククラスなどを拡張できます。

拡張メソッドは、実際には静的クラスで定義されている特別な種類の静的メソッドです。

DateTimeクラスはすでに上記で取り上げられているため、説明のためにこのクラスを取り上げていません。

以下は例です

//これは、1つのメソッド(Add)のみを持つ既存のCalculatorクラスです

public class Calculator 
{
    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }

}

// Below is the extension class which have one extension method.  
public static class Extension
{
    // It is extension method and it's first parameter is a calculator class.It's behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){
       return num1 / num2;
    }   
}

// We have tested the extension method below.        
class Program
{
    static void Main(string[] args)
    {
        Calculator cal = new Calculator();
        double add=cal.Add(10, 10);
        // It is a extension method in Calculator class.
        double add=cal.Division(100, 10)

    }
}
0