C#继承和方法签名

本文关键字:方法 继承 | 更新日期: 2023-09-27 18:19:26

我正在开发一个类,该类需要根据传入的对象类型运行不同的处理方法。我认为重载可能在这里起作用,但我有一个问题。假设我有两个接口:

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签名,因为从技术上讲,该接口也是实现的。

谢谢你的帮助。

C#继承和方法签名

这取决于如何调用方法。

例如,假设您有Email : IEmailSpecialEmail : 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)

根据C#规范(第7.4.3节)

"如果派生类中的任何方法都适用,则基类中的方法不是候选方法"

如果传入ISpecialEmail,则public void ProcessEmail (ISpecialEmail email)应该是调用的函数。不过,请小心将其强制转换为IEmail,因为这会更改优先级。如果您将所有类型为IEmailISpecialEmail的电子邮件合并为IEmail的一个List进行处理,它们都将通过IEmail版本的函数。