Project
ReSharper
Priority
Show-stopper
Type
Bug
Fix versions
5.0
State
Fixed
Assignee
Olga Lobacheva
Subsystem
PSI
Affected versions
No Affected versions
Fixed in build
No Fixed in build
  • Created by   Evgeny Pasynkov
    2 years ago (18 Dec 2009 13:10)
  • Updated by   Olga Lobacheva
    18 months ago (14 Jul 2010 18:54)
  • Jira: RSRP-143762
    (history, comments)
 
RSRP-143762 Overload resolution fails
0
Issue is visible to: All Users
  The issue is visible to the selected user group only
http://rsdn.ru/forum/dotnet/3635090.flat.aspx#3635090

using System;

class B
{
    public virtual void Foo(int x)
    {
        Console.WriteLine(1);
    }

    public virtual void Foo(long x, long y = 1)
    {
        Console.WriteLine(2);
        Console.WriteLine(y);
    }

    public virtual void Foo(object x)
    {
        Console.WriteLine(3);
    }
}

class C : B
{
    public override void Foo(int y)
    {
        Console.WriteLine(4);
    }

    public override void Foo(object x)
    {
        Console.WriteLine(5);
    }
}

class D : C
{
    public override void Foo(int x)
    {
        Console.WriteLine(6);
    }

    public override void Foo(long a, long b = 2)
    {
        Console.WriteLine(7);
        Console.WriteLine(b);
    }

    public override void Foo(object x)
    {
        Console.WriteLine(8);
    }


    static void Main()
    {
        C c = new D();
        c.Foo(x:1);
    }
}


http://www.rsdn.ru/forum/dotnet/3635577.1.aspx

На самом деле результат будет 7 1.

При построении группы методов для overload resolution методы, имеющие модификатор override, игнорируются. Получается три метода Foo(int), Foo(long, long), Foo(object). Но применяется такое правило из спецификации C# 4.0:

For virtual and abstract members, the parameter names in overrides may be different from those in the declaration. For the purposes of overload resolution, the parameter names that apply are the ones that appear in the most specific override of the function member with respect to the static type of the target of the member access.


Static type у объекта, у которого вызывается метод — C. Значит, если какой-то из методов переопределен в классе C, то нужно взять имена параметров оттуда, а иначе — из исходной декларации в базовом классе B. Получается Foo(int y), Foo(long x, long y = 1), Foo(object x). При вызове передается один именованный аргумент x:1. Значит, у первого метода не задан обязательный параметр y, и применимыми окажутся методы Foo(long x, long y = 1), Foo(object x). Они оба определены в одном классе, поэтому нужно выбрать лучший из них, исходя из их сигнатуры и передаваемых аргументов. Это Foo(long x, long y = 1), так как неявное преобразование из 1 в long лучше, чем преобразование из 1 в object (потому что есть неявное преобразование из long в object, но не наоборот). Параметру y соответствует значение по умолчанию 1, но оно не влияет на overload resolution (потому что только явно указанные аргументы влияют). Таким образом, вызывается метод с сигнатурой Foo(long, long) и аргументами (1, 1). Так как этот метод виртуальный, а runtime тип объекта D, то в runtime вызывается метод с соответствующей сигнатурой в классе D, и печатает 7 1.
Comments (0)
 
History
 
Linked Issues (?)
 
TeamCity Changes (1)
 
Issue has no comments