2015-06-23 2 views
1

Я пишу этот кусок кода в одном из моего проекта C#:Мой перегружен общий метод не называется

public static class GetAppendReceiver 
{ 
    public static AppendReceiver<DataType> Get<DataType>(AppendReceiver<DataType>.DataProcessor processor0, int delayIn = 0) 
    { 
     throw new InvalidOperationException(); 
    } 

    public static AppendReceiver<string> Get(AppendReceiver<string>.DataProcessor processor0, int delayIn = 0) 
    { 
     return new StringAppendReceiver(processor0, delayIn); 
    } 
} 

public abstract class AppendReceiver<DataType> 
{ 
    public delegate void DataProcessor(DataType data); 
    ... 
} 

AppendReceiver<DataType> является абстрактным классом, DataProcessor является типом делегата.

При вызове GetAppendReceiver.Get со строкой DataProcessor Я ожидаю, что вызывается перегруженная функция, но я получаю InvalidOperationException.

Вот мой призыв:

class ClassA<DataType> 
{ 
    public void RegisterAppendReceiver(AppendReceiver<DataType>.DataProcessor receiver) 
    { 
     appendReceivers.Add(GetAppendReceiver.Get(receiver, Delay)); 
    } 
} 

Пример RegisterAppendReceiver вызова:

myObject.RegisterAppendReceiver(myMethod); 

Где myMethod определяется следующим образом:

public void writeMessage(string strMessageIn) 

Мой вопрос, почему я получаю неправильно перегрузка называется, и как я могу заставить язык вызвать перегрузку, которую я хочу?

Благодарим за помощь!

ответ

2

Эрик Липперт отвечает на этот вопрос сжато в своей статье Generics are not Templates

Я не хочу, чтобы скопировать всю статью. Таким образом, имеет значение следующее:

Мы делаем разрешение перегрузки один раз и запекаем в результате.

Так что C# компилятор решает, в то время он компилирует RegisterAppendReceiver, какая перегрузка «GetAppendReceiver.Get» он собирается позвонить. Поскольку в этот момент единственное, что он знает о DataType, заключается в том, что DataType может быть чем угодно вообще, он компилируется в вызове перегрузки, который принимает AppendReceiver.DataProcessor, а не AppendReceiver.DataProcessor.

Для сравнения, компилятор C++ не ведет себя так. Каждый раз, когда генерируется общий вызов, компилятор снова выполняет замену. Это одна из причин, по которой компиляторы C++ намного медленнее, чем компиляторы C#.

+0

Хорошо, я понимаю разницу, спасибо за разъяснение. Есть ли способ, которым я могу достичь своей цели с помощью C#? – AMDG

+0

В статье Эрика, динамический будет делать это, но он решит тип во время выполнения, а не время компиляции. Пока производительность не проблема, это сработает. –

+0

@AMDG Вы также можете просто использовать наследование в этом случае. Это мне кажется классическим примером шаблона * abstract factory * - GoF прекрасно описывает, как это сделать, используя стандартное наследование. – atlaste

Смежные вопросы