3

拡張メソッドと継承の間に何らかの関係を築くことはできますか?

newそれとも、C# で -keywordを使用するのと同様の拡張メソッドですか?

4

4 に答える 4

9

両方の質問にいいえ。拡張メソッドは、実際には、拡張機能が最初のパラメーターとして操作するオブジェクトを取るメソッドです。

キーワードは、クラスのnewインスタンスにリソースを割り当てるために使用されます。null拡張メソッドはインスタンスで動作しますが、最初のパラメーターとしてインスタンス (またはその型) を必要とするため、新しい置換として機能することはできません。

検討:

public static class StringExtensions
{
    public static string Reverse(this string _this)
    {
        // logic to reverse the string
    }
}

この静的メソッドは、次の 2 つの方法で呼び出すことができます。

// as an extension method:
string s = "hello world";
string t = s.Reverse();

// as a static method invocation:
string t = StringExtensions.Reverse(s);

いずれの場合も、コンパイラは MSIL の呼び出しを変更して、2 番目の呼び出しをマップします。コンパイル後、-キーワードなしでは拡張メソッドを対応する静的メソッドから認識する方法はありませんthis

要約する

  • 拡張機能はクラスの一部ではありません
  • 拡張機能は継承とは関係ありません。実際には継承されない静的メソッドです。
  • 拡張機能は、キーワードのようにクラスをインスタンス化することはできませんnew(ただし、メソッド内でクラスをインスタンス化することはもちろん可能です)。
  • 拡張機能はで動作できnullますが、それ以外の場合、そのクラスのメソッドはNullReferenceException. これは、インスタンスが単に静的メソッドの最初のパラメーターであるという事実から生じます。
  • (上記のように)シールされたクラスを拡張することは可能ですがstring、これは継承では不可能です (シールされたクラスから派生することはできません)。

編集: Tigran とFloran
は、この質問がnew modifierに関するものであることをほのめかしました。

拡張メソッドは、キーワードのどちらの意味とも関係ありません。newただし、相互に関連するいくつかの考えがあります。これ以上混乱しないことを願っています。もしそうなら、「編集」の上の部分に固執してください;)

  • 新しい修飾子について:

    • new 修飾子は、既存のメソッドを非表示にするために使用されます。宣言は静的メソッドであるため、拡張メソッドは既存のメソッドを非表示にすることはできません。コンパイル時に警告やエラーが発生することさえありません。
    • new 修飾子では、メソッド (またはプロパティ) が既に存在し、アクセス可能である必要があります。拡張メソッドは、同じ署名を持つメソッドがまだ存在しない場合にのみ機能します。
    • new 修飾子は、継承によってクラスの拡張に作用します。つまり、すべてのメソッドはすでに継承されています。拡張メソッドはクラスのインスタンスで動作し、クラスとの継承関係はありません。
       
  • 新しいジェネリック制約について:

    • この制約は、許可されるジェネリック型を、アクセス可能なパラメーターなしのコンストラクターを持つものに制限します。拡張メソッドは、ジェネリックとは何の関係もありません。
    • 拡張メソッド自体はジェネリックにすることができ、パラメーター (つまり、それが操作できるクラス) は新しいジェネリック制約によって制限できます。

      // this ext. method will only operate on classes that inherit 
      // from ICollectible and have a public parameterless constructor
      public static int CalculateTotal<T>(this T _collectible)
          where T : ICollectible, new()
      {
          // calculate total
      }
      
于 2012-04-08T16:45:58.987 に答える
3

いいえ、拡張メソッドは既存のクラスの機能を拡張するだけです。

拡張メソッドを使用すると、新しい派生型を作成したり、再コンパイルしたり、元の型を変更したりすることなく、既存の型にメソッドを「追加」できます。

拡張メソッドに関するMSDN(C#プログラミングガイド)を参照してください。

このnewキーワードはoverride、基本クラスの非仮想メソッドと静的メソッドを使用できるようにするために必要です。

public class A
{
   public virtual void One();
   public void Two();
}

public class B : A
{
   public override void One();
   public new void Two();
}

B b = new B();
A a = b as A;

a.One(); // Calls implementation in B
a.Two(); // Calls implementation in A
b.One(); // Calls implementation in B
b.Two(); // Calls implementation in B

vsでこのリンクをnewoverrideチェックしてください。

于 2012-04-08T16:48:47.400 に答える
1

いいえ。拡張メソッドは、「拡張」される型のオブジェクトを最初の引数として受け取る、個別の静的クラスの構文糖衣です。継承とはまったく関係ありません。このメソッドは、他のクラスと同様に、「拡張」クラスのパブリック メンバーにのみアクセスできます。

于 2012-04-08T16:46:12.013 に答える
0

拡張メソッドは、継承やnewキーワード (またはコンストラクター) とは関係ありません。ソースコードを持っていないクラスに機能を追加したい場合、より良いコードを可能にします。ソース コードがある場合にも機能しますが、通常はソース コードを変更するだけの方が適切です。

たとえば、これを実行できるようにしたい場合があります。

string text = "this is my string";
int count = text.WordCount();

このメソッドはクラスに存在しないため、次のStringようにする必要があります。

string text = "this is my string";
int count = MyCommon.WordCount(text);

whereWordCount()は、ある種の一般的なライブラリの静的メソッドです。

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

public static class MyExtensions
{
    public static int WordCount(this String str)
    {
        return str.Split(new char[] { ' ', '.', '?' }, 
                         StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

クラスtext.WordCount()で定義された通常のメソッドであるかのように機能します。Stringそれだけで少し使いやすくなります。

hereから取得したコードも読むことをお勧めします。

于 2012-04-08T19:49:32.300 に答える