4

(また迷惑な質問です... )

以前にこれを尋ねた後-(これは私の質問に部分的に関連しています)-私は答えを得ました:

C# 4 仕様の §7.6.5.1 を参照してください。

候補メソッドのセットは、最も派生した型のメソッドのみを含むように削減されます。セット内のメソッド CF ごとに (C はメソッド F が宣言されている型)、C の基本型で宣言されたすべてのメソッドが削除されます。セット。

わかった。

私はこのコードを持っています://.Dump() is like a WriteLine command...

 public class Base
    {
        public void Foo(string strings)  { "1".Dump();}
        public virtual void  Foo(object strings)  { "2".Dump();}
    }

    public class Child : Base
    {

        public override void  Foo(object strings)  { "4".Dump();}
    }

しかし、このコード:

Child c = new Child();
c.Foo("d");

を放出します:"1"

ちょっと待って ...

私たちはそれを言いませんでしたis reduced to contain only methods from the most derived types:か?

子には、その父親からの 1 つの関数public void Foo(string strings)と、NEARER オーバーライド関数があります。

では、なぜ彼はそのベースの機能を選択したのですか? 継承された関数はオーバーライドよりも近いですか?

オーバーライドが実行時にあるという事実に関連していますか?

助けてください。

編集

この状況はどうですか?

public class Base
    {    
        public virtual void  Foo(int x)  { "1".Dump();}
    }

    public class Child : Base
    {
        public override void  Foo(int x)  { "2".Dump();}
        public void Foo(object x) { "3".Dump();}    
    }

void Main()
{
    Child c = new Child();
    c.Foo(6); //emits "3"
}
4

4 に答える 4

6

それは、あなたの子供が物を取るからです。

public class Child : Base
{
    public override void Foo(object strings)  { "4".Dump();}
}

文字列にすると、子が呼び出されます。

public class Child : Base
{
    public override void Foo(string strings)  { "4".Dump();}
}

なぜこれ?

コンパイラーは、子にパラメーターがあることを認識しているため、基本クラスではobject変換する必要があり、文字列としてすぐに利用できます。string

したがって、ベース 1 を呼び出します。

オーバーライドされた関数は、子クラスでより近くにありますが。しかし、ここではルールが子とベースで異なります。子にはオブジェクトがあり、ベースには文字列があります。object両方持っていても両方持っていても公平だったstring.

Jon Skeet のC# in Depth Overloading セクションでこれを読みました

于 2012-05-28T07:35:31.303 に答える
3

ここには、オーバーロードとオーバーライドという 2 つの概念が混同されています。オーバーロードとは、同じ名前の関数に対して複数のシグネチャを持ち、そのシグネチャに基づいて呼び出す 1 つを選択するという概念です。オーバーライドは、派生クラスでメソッドを再定義する概念です。

子クラスがメソッド定義の 1 つをオーバーライドしたかどうかは、どちらのメソッドのシグネチャも変更しないため、どの関数が呼び出されるかはまったく問題ではありません。定義と構造により、メソッドをオーバーライドしてもその署名は変更できません

したがって、署名が変更されていない場合、署名に基づいて呼び出す正しい関数を決定するためのまったく同じメカニズムが、親クラスと子クラスの両方に対して使用されます。

アップデート

実際には、Eric Lippert が彼のブログで指摘しているように、これにはもう少し続きがあります。実際、子クラスのオーバーロードに一致するメソッドがある場合、基本クラスのメソッドは検索されません。理由は正気です - 重大な変更を避ける - しかし、基本クラスと子クラスの両方を所有している場合、結果はいくぶん非論理的です。

私は Jon Skeet に反論することしかできません。

于 2012-05-28T07:45:54.673 に答える
1

ここでは、基本クラスのメソッドがそれに基づいて選択されていると思いますdataType

基本クラスのメソッドと完全c.Foo("d");に一致し、それに対してオーバーライドされたメソッドがないderived classため、基本クラスのメソッドが呼び出されます。

于 2012-05-28T07:36:00.657 に答える
1

ベスト マッチ ルールが表示されます 。

stringlike an 引数をFoo(..)関数に渡します。

基本クラスには がありFoo(string..)、代わりに子クラスにはありません。したがって、この場合、 base のメソッドが最終的に選択されます。

于 2012-05-28T07:35:57.810 に答える