6

これが C# 4+ 固有のものかどうかはわかりませんが、これに気付きました。

次のクラスを検討してください。

class Base
{
  protected void Foo(object bar, DayOfWeek day)
  {
  }
}

class Program : Base
{
  protected void Foo(object bar, object baz)
  {
  }

  void Bar(DayOfWeek day)
  {
    Foo(new { day }, day);
  }
}

Fooinへの呼び出しはBarに解決されFoo(object, object)ます。

それを次のように変更しながら:

class Base
{

}

class Program : Base
{
  protected void Foo(object bar, object baz)
  {
  }

  protected void Foo(object bar, DayOfWeek day)
  {
  }

  void Bar(DayOfWeek day)
  {
    Foo(new { day }, day);
  }
}

Fooinへの呼び出しはBarに解決されFoo(object, DayOfWeek)ます。

私の理解では、2 番目の例のように常に解決する必要があります。

これは「バグ」ですか、それとも私の理解不足 (または無知) ですか?

アップデート:

答えてくれてありがとう。私が見つけたようbase.に、基本クラスでメソッドを呼び出すために使用できます。ただし、ミックスに別の派生クラスを追加すると、問題が再発します。

class Base
{
  protected void Foo(object bar, DayOfWeek day)
  {
  }
}

class Program : Base
{
  protected void Foo(object bar, object baz)
  {
  }

  void Bar(DayOfWeek day)
  {
    base.Foo(new { day }, day);
  }
}

class Derived : Program
{
  void Baz(DayOfWeek day)
  {
    base.Foo(new { day }, day);
  }
}

base.呼び出しは で機能しますがProgram、 に解決さFoo(object, object)Derivedます。

で「冗長な」メソッドを作成することなくFoo(object,DayOfWeek)、それからどのように呼び出すでしょうか?DerivedProgram

4

4 に答える 4

4

Eric Lippertのブログをチェックアウトする必要があります-特にこの記事: http: //blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx

ただし、事実上、過負荷解決アルゴリズムは、現在のクラスで呼び出すことができる過負荷を検索し、現在のクラスで代替が見つからない場合にのみ基本クラスで代替を検索します。

最初のケースでは、Foo(object, object)オーバーロードが適用されるため、それ以上の検索は実行されません。

2番目のケースでは、Foo(object DayOfWeek)が優れているため、使用されます。

詳細については、Ericの記事をお読みください。

于 2012-09-03T05:27:01.717 に答える
1

他の人が指摘したように、この問題はオーバーロードの解決方法に関連しています。それに追加するだけです:

Base.Fooだった場合、これを実行して以内publicに到達できます(オーバーライドされていないと仮定します):Base.FooDerivedBase.Foo

((Base)this).Foo(new { day }, day);

また、オーバーライドする ( に変更できる場合) または明示的に非表示にするオプションがあるBase.Fooためvirtual、内で呼び出した場合Base.Fooでも、が呼び出されます。Programbase.FooDerivedBase.Foo

class Program : Base
{
  protected void Foo(object bar, object baz)
  {
  }

  protected new void Foo(object bar, DayOfWeek baz)
  {
    base.Foo(bar, baz);
  }

  void Bar(DayOfWeek day)
  {
    base.Foo(new { day }, day);
  }
}

補足として: 通常、派生クラスは、基本クラスのオーバーロードよりも具体的なパラメーターの型を持つオーバーロードを提供します (例: Object.Equals(object)) String.Equals(string)

より少ない (または同等の) 特定のパラメーター タイプのケースがある場合でも、基本メソッドをオーバーライドするか (たとえばObject.Equals(object)String.Equals(object)-> overrides Object.Equals(object))、別のメソッド名を付けるだけです。

于 2012-09-03T07:23:59.930 に答える
1

スペックは妥当だと思います。派生クラスのプログラマーは、基本クラスでの非相対メソッドの実装を知る必要はありません。そうでなければ、不運な人が基本クラスのメソッドよりも互換性の低いメソッドを作成した場合 (そして、この人は基本クラスの詳細を知りません)、基本クラスのメソッドが呼び出されます。

于 2012-09-03T05:39:30.163 に答える