2013-06-20 5 views
5

Я работаю над классом, который должен запускать другой метод обработки, основанный на типе объекта, в котором я проходил. Я думал, что перегрузка может работать здесь, но у меня есть вопрос. Допустим, у меня есть два интерфейса:Подписи наследования и методов на C#

public interface IEmail 
{ 
     Some properties ... 
} 

и

public interface ISpecialEmail : IEmail 
{ 
    Some more properties.... 
} 

и класс для обработки этих объектов:

public class EmailProcessor 
{ 

     public void ProcessEmail (IEmail email) 
     { 
      do stuff; 
     } 

     public void ProcessEmail (ISpecialEmail email) 
     { 

      do different stuff 
     } 
} 

Мой вопрос, в том, что ISpecialEmail наследует от IEmail, таковы сигнатуры методов, достаточно разные, чтобы допускать перегрузку? Моя оригинальная мысль заключается в том, что электронные письма ISpecialEmail также запускают подпись IEmail, так как технически этот интерфейс также реализуется.

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

+1

Если он компилируется, тогда он должен работать нормально. Невозможно, чтобы компилятор/среда выполнения позволяла одному вызову метода запускать две отдельные функции одновременно – musefan

+0

Почему бы вам не попробовать скомпилировать программу и не увидеть, что происходит. У вас уже есть большая часть кода, необходимого для проверки этого. Почему вы не попробовали это, прежде чем публиковать его здесь? – Servy

+1

@musefan Обратите внимание, что речь идет не только о двусмысленности, но о том, какая перегрузка будет выбрана. Вам нужно сделать больше, чтобы увидеть, что * если * он компилируется, вам нужно определить, какая перегрузка компилятор считает «лучшей». Тем не менее, это все еще простая вещь; это просто означает, что вам нужно запустить его один раз после его компиляции. – Servy

ответ

2

Это зависит от того, как вы называете методы.

Например, предположим, что у вас есть Email : IEmail и SpecialEmail : ISpecialEmail. Если вы объявили список писем:

List<IEmail> emails = new List<IEmail> {new Email(), new SpecialEmail()}; 

А потом побежал

foreach (var email in emails) { EmailProcessor.ProcessEmail(email) } 

Он позвонит public void ProcessEmail (IEmail email) для как - потому связывании вызов происходит во время компиляции (т.е. она не будет работать так как вы хотели).

Было бы также ошибкой, если вы сделали что-то вроде:

var email = GetEmail(); // returns either IEmail or IExtendedEmail 
EmailProcessor.ProcessEmail(email); // Would ONLY call ProcessEmail(IEmail) 

Таким образом, полиморфизм потерпит неудачу с этими подписями.

Тем не менее, следующее будет работать:

var email = GetEmail(); // returns only IEmail 
var extendedEmail = GetExtendedEmail(); // returns only IExtendedEmail 
EmailProcessor.ProcessEmail(email); // Would all ProcessEmail(IEmail) 
EmailProcessor.ProcessEmail(extendedEmail); // Would call ProcessEmail(IExtendedEmail) 
+0

Целью является использование фабрики для получения электронной почты и просто запуск emailProcessor.ProcessEmail. Как бы вы пошли на принудительный полиморфизм? – Mike

+1

@Mike Have 'ProcessEmail' является методом' IEmail' или имеет достаточно информации только для этой информации для обработки любого типа, а затем позволяет различным реализациям по-разному перегружать элементы интерфейса для достижения различного поведения. – Servy

+1

Чтобы заставить полиморфизм работать, вам нужно будет переместить подпись ProcessEmail() в состав IEmail, а затем иметь конкретные реализации в классах электронной почты/расширенной электронной почты. Однако это означало бы, что код для обработки электронных писем будет внутри объектов электронной почты, которые вам могут не понадобиться, - что сказал @Servy :) –

2

В соответствии с С # спецификации (раздел 7.4.3)

«методы в базовом классе не являются кандидатами, если какой-либо метод в производном классе применимый»

public void ProcessEmail (ISpecialEmail email) должна быть функция, вызываемая если ISpecialEmail передается в. Будьте осторожны, о приведении его вниз к IEmail, хотя, как это изменит приоритет. Если вы комбинируете все электронные письма, оба типа IEmail и ISpecialEmail в одном List из IEmail s для обработки, все они пройдут через функцию IEmail.