C # правила перегрузки функций - PullRequest
9 голосов
/ 16 августа 2010

Каковы правила, касающиеся перегрузки функции?

У меня есть следующий код:

public T genericFunc<T>() where T : Component, new()
{
    T result = new T();
    overloadedFunction( result );
}

private overloadedFunction ( Component c ) // catch all function

private overloadedFunction ( DerivedFromComponent dfc) // specific function

, когда я вызываю вышеуказанный код с помощью:

genericFunc<DerivedFromComponent>();

Iожидаем, что будет вызвана более конкретная перегруженная функция, однако вместо этого вызывается функция catch all, почему?При выполнении вышеприведенного кода тип T действительно является DerivedFromComponent, я подумал, что CLR выбрал наилучшее из возможных совпадений во время выполнения!

Ответы [ 2 ]

15 голосов
/ 16 августа 2010

Компилятор выполняет разрешение перегрузки в пределах genericFunc , когда этот метод компилируется . В этот момент он не знает, какой тип аргумента вы собираетесь предоставить, поэтому он знает только, что может вызвать первую из ваших перегрузок.

Ваш пример использования обобщений усложняет жизнь, но перегрузки всегда разрешаются во время компиляции (при условии, что вы не используете dynamic).

Простой пример, не использующий дженерики:

void Foo(string text) { }
void Foo(object o) {}
...
object x = "this is a string";
Foo(x);

вызовет вторую перегрузку, потому что тип времени компиляции x является просто объектом.

Подробнее об этом читайте в моей недавней статье о перегрузке .

3 голосов
/ 16 августа 2010

Джон Скит прав в том, что разрешение перегрузки определяется во время компиляции.Я подумал, что добавлю еще один ответ, который не был предметом вашего вопроса, но тем не менее интересно отметить.

В C # 4 ключевое слово dynamic может использоваться для отсрочки разрешения перегрузки до времени выполнения.Рассмотрим следующий фрагмент кода:

Base!
Derived!


class Base {
}

class Derived : Base {
}

void DoSomething(Base x) {
    Console.WriteLine("Base!");
}

void DoSomething(Derived x) {
    Console.WriteLine("Derived!");
}

void DoSomething<T>() where T: Base, new() {
    dynamic x = new T();
    DoSomething(x);
}

void Main()
{
    DoSomething<Base>();
    DoSomething<Derived>();
}
...