Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload resolution oddity

Not sure if this is C# 4+ specific, but just noticed this.

Consider the following classes:

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);
  }
}

The call to Foo in Bar, resolves to Foo(object, object).

While changing it to:

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);
  }
}

The call to Foo in Bar, resolves to Foo(object, DayOfWeek).

My understanding is that it should always resolve as in the second example.

Is this a 'bug' or just my lack of understanding (or ignorance)?

Update:

Thanks for the answers. As I have found out, one can use base. to call the method in the base class. The problem comes back however when adding another derived class in the mix.

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);
  }
}

The base. call works in Program, but then resolves to Foo(object, object) in Derived.

How would one call Foo(object,DayOfWeek) from Derived then without having to create 'redundant' methods in Program ?

like image 299
leppie Avatar asked Sep 03 '12 05:09

leppie


Video Answer


1 Answers

I think for resolving method call it looks in its class first, since DayOfWeek can be passed as object type, it calls class own method, not the one from the base class.

In the second case, the method call resolves to a the more particular type parameter, therefore Foo(object bar, DayOfWeek day) gets called.

From MSDN - Method resolution.

methods in a base class are not candidates if any method in a derived class is applicable (Section 7.5.5.1).

  • Given the set of applicable candidate function members, the best function member in that set is located.
  • If the set contains only one function member, then that function member is the best function member.
  • Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Section 7.4.2.2.
  • If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a compile-time error occurs.
like image 147
Habib Avatar answered Oct 19 '22 07:10

Habib