web-dev-qa-db-ja.com

メソッドシグネチャの新しいキーワード

リファクタリングを実行しているときに、次の例のようなメソッドを作成することになりました。単純化のためにデータ型が変更されました。

以前、次のような割り当てステートメントがありました。

MyObject myVar = new MyObject();

偶然にこれにリファクタリングされました:

private static new MyObject CreateSomething()
{
  return new MyObject{"Something New"};
}

これは、私の側でのカット/ペーストエラーの結果でしたが、private static newnewキーワードは有効であり、コンパイルされます。

質問:メソッドシグネチャでnewキーワードは何を意味しますか? C#3.0で導入されたものだと思いますか?

これはoverrideとどう違いますか?

112
p.campbell

MSDNの新しいキーワードリファレンス:

MSDNリファレンス

以下は、私がMicrosoft MVPからネット上で見つけた、意味のある例です。 Link to Original

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

オーバーライドは、非常に特定の場合にのみ使用できます。 MSDNから:

非仮想メソッドまたは静的メソッドをオーバーライドすることはできません。オーバーライドされたベースメソッドは、仮想、抽象、またはオーバーライドである必要があります。

したがって、非仮想メソッドおよび静的メソッドを「オーバーライド」できるようにするには、「new」キーワードが必要です。

98
Kelsey

いいえ、実際には「新しい」ものではありません(しゃれを許してください)。基本的に、メソッドを「隠す」ために使用されます。 IE:

public class Base
{
   public virtual void Method(){}
}

public class Derived : Base
{
   public new void Method(){}
}

その後、これを行う場合:

Base b = new Derived();
b.Method();

Baseのメソッドは呼び出されるメソッドであり、派生のメソッドではありません。

詳細: http://www.akadia.com/services/dotnet_polymorphism.html

あなたの編集について:私が与えた例では、「new」を使用する代わりに「override」する場合、b.Method( );ポリモーフィズムのために、派生クラスのメソッドが呼び出されます。

59
BFree

他の人が説明したように、既存のメソッドを隠すために使用されます。親クラスで仮想ではないメソッドをオーバーライドするのに役立ちます。

「新しい」メンバーの作成はポリモーフィックではないことに注意してください。オブジェクトを基本型にキャストすると、派生型のメンバーは使用されません。

基本クラスがある場合:

_public class BaseClass
{
    public void DoSomething() { }
}
_

そして、派生クラス:

_public class DerivedType : BaseClass
{
    public new void DoSomething() {}

}
_

DerivedTypeの型を宣言してからキャストすると、メソッドDoSomething()はポリモーフィックではなく、派生クラスではなく基本クラスのメソッドを呼び出します。

_BaseClass t = new DerivedType();
t.DoSomething();// Calls the "DoSomething()" method of the base class.
_
22
Dan Herbert

ドキュメントから:

派生クラスのメソッドの前に新しいキーワードがある場合、そのメソッドは基本クラスのメソッドから独立していると定義されます。

これが実際に意味するもの:

別のクラスから継承し、同じ署名を共有するメソッドがある場合、親クラスから独立するように「新規」として定義できます。つまり、「親」クラスへの参照がある場合はその実装が実行され、子クラスへの参照がある場合はその実装が実行されます。

個人的には、クラス階層が間違っていることを意味するため、「新しい」キーワードを避けるようにしていますが、役に立つ場合もあります。 1つの場所は、バージョン管理と後方互換性のためです。

このためのMSDN には多くの情報があります。

7
jonnii

つまり、メソッドは、基本クラスによって継承された同じ名前のメソッドを置き換えます。あなたの場合、基本クラスにその名前のメソッドがない可能性があります。つまり、新しいキーワードはまったく不要です。

3
Robin Clowers

長い話-必須ではなく、動作を変更せず、読みやすくするために純粋に存在します。

そのため、VSでは少し波打ったように見えますが、コードはコンパイルされ、期待どおりに完全に正常に実行されます。

newキーワードを作成する価値があるのは、開発者が「はい、基本メソッドを非表示にしていることを知っています。関連することは何もしていません。 virtualまたはoverriden(多態性)-独自のメソッドを作成したいだけです。

私には少し奇妙ですが、おそらくJavaのバックグラウンドから来たので、C#継承とJavaJavaでは、finalで指定されない限り、メソッドはデフォルトで仮想です。 C#、メソッドはvirtualで指定されない限り、デフォルトでfinal/concreteです。

3
Don Cheadle

[〜#〜] msdn [〜#〜] から:

新しい修飾子を使用して、基本クラスから継承されたメンバーを明示的に非表示にします。継承されたメンバーを非表示にするには、派生クラスで同じ名前を使用して宣言し、新しい修飾子で変更します。

1
Doug R

この落とし穴に注意してください。
基本クラスに実装されているインターフェイスにメソッドが定義されています。次に、インターフェイスのメソッドを隠す派生クラスを作成しますが、派生クラスをインターフェイスの実装として明示的に宣言しないでください。その後、インターフェイスへの参照を介してメソッドを呼び出すと、基本クラスのメソッドが呼び出されます。ただし、派生クラスがインターフェイスを具体的に実装している場合、そのメソッドは使用されている参照のタイプに関係なく呼び出されます。

interface IMethodToHide
{
    string MethodToHide();
}

class BaseWithMethodToHide : IMethodToHide
{
    public string MethodToHide()
    {
        return "BaseWithMethodToHide";
    }
}

class DerivedNotImplementingInterface   : BaseWithMethodToHide
{
    new public string MethodToHide()
    {
        return "DerivedNotImplementingInterface";
    }
}

class DerivedImplementingInterface : BaseWithMethodToHide, IMethodToHide
{
    new public string MethodToHide()
    {
        return "DerivedImplementingInterface";
    }
}

class Program
{
    static void Main()
    {
        var oNoI = new DerivedNotImplementingInterface();
        IMethodToHide ioNoI = new DerivedNotImplementingInterface();

        Console.WriteLine("reference to the object type DerivedNotImplementingInterface calls the method in the class " 
            + oNoI.MethodToHide());
        // calls DerivedNotImplementingInterface.MethodToHide()
        Console.WriteLine("reference to a DerivedNotImplementingInterface object via the interfce IMethodToHide calls the method in the class " 
            + ioNoI.MethodToHide());
        // calls BaseWithMethodToHide.MethodToHide()
        Console.ReadLine();

        var oI = new DerivedImplementingInterface();
        IMethodToHide ioI = new DerivedImplementingInterface();

        Console.WriteLine("reference to the object type DerivedImplementingInterface calls the method in the class " 
            + oI.MethodToHide());
        // calls DerivedImplementingInterface.MethodToHide()
        Console.WriteLine("reference to a DerivedImplementingInterface object via the interfce IMethodToHide calls the method in the class " 
            + ioI.MethodToHide());
        // calls DerivedImplementingInterface.MethodToHide()
        Console.ReadLine();

    }
}
0