C#继承和方法签名
我正在处理一个类,该类需要根据传入的对象类型运行不同的处理方法。我想超载可能在这里起作用,但我有一个问题。假设我有两个接口:C#继承和方法签名,c#,interface,overloading,C#,Interface,Overloading,我正在处理一个类,该类需要根据传入的对象类型运行不同的处理方法。我想超载可能在这里起作用,但我有一个问题。假设我有两个接口: public interface IEmail { Some properties ... } 及 以及处理这些对象的类: public class EmailProcessor { public void ProcessEmail (IEmail email) { do stuff; }
public interface IEmail
{
Some properties ...
}
及
以及处理这些对象的类:
public class EmailProcessor
{
public void ProcessEmail (IEmail email)
{
do stuff;
}
public void ProcessEmail (ISpecialEmail email)
{
do different stuff
}
}
我的问题是,由于ISPSpecialMail继承自IEmail,这些方法签名是否足够不同,以允许重载?我最初的想法是,ISPSpecialMail电子邮件也会触发IEmail签名,因为从技术上讲,该接口也是实现的
谢谢您的帮助。这取决于您如何调用这些方法 例如,假设您有
Email:IEmail
和specialmail:isspecialmail
。如果您声明了电子邮件列表:
List<IEmail> emails = new List<IEmail> {new Email(), new SpecialEmail()};
它将调用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)
根据C#规范(第7.4.3节)
“如果派生类中的任何方法都适用,则基类中的方法不是候选方法”
如果传入了
ISpecialEmail
,则应调用public void ProcessEmail(ISpecialEmail email)
函数。不过,在将其转换为IEmail
时要小心,因为这会改变优先级。如果您将所有电子邮件(包括IEmail
和ISpecialEmail
类型)合并到一个IEmail
列表中进行处理,它们都将通过IEmail
版本的函数进行处理。如果它编译,那么它应该可以正常工作。编译器/运行时不可能让一个方法调用同时运行两个单独的函数。为什么不试着编译程序并实际查看发生了什么。您已经拥有了测试此功能所需的大部分代码。“你为什么不在发布之前尝试一下呢?”穆塞凡指出,这不仅是一个是否存在歧义的问题,而且是一个选择哪种过载的问题。您确实需要做更多的工作来查看它是否编译,您需要确定编译器认为哪个重载是“最好的”。尽管如此,这仍然是一件简单的事情;这只意味着编译后需要运行一次。@Servy:是的,发布后我想到了一篇我不久前读过的“优先级”文章。我想这会有一些话要说,我知道它会正确编译,我只是不确定是否有人知道它是否会选择正确的方法。不幸的是,这是web服务的一部分,在测试它之前,我还有一段路要走。不过,感谢您的评论。我们的目标是使用工厂获取电子邮件,只需运行emailProcessor.ProcessEmail方法。那么,您将如何实施多态性呢?@Mike让ProcessEmail
成为IEmail
的一种方法,或者在这些信息中有足够的信息来处理任何一种类型,然后让不同的实现以不同的方式重载接口成员,以实现不同的行为。要使多态性发挥作用,您需要将ProcessEmail()签名移动到IEmail中,然后在电子邮件/扩展电子邮件类中实现具体的实现。然而,这意味着处理电子邮件的代码将位于您可能不想要的电子邮件对象中-正如@Servy所说:)
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)