【问题标题】:C# inheritance and method signaturesC# 继承和方法签名
【发布时间】:2013-06-20 16:11:23
【问题描述】:

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

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

感谢您的帮助。

【问题讨论】:

  • 如果它编译,那么它应该可以正常工作。编译器/运行时不可能让单个方法调用同时运行两个单独的函数
  • 您为什么不尝试编译程序并实际看看会发生什么。您已经拥有了测试它所需的大部分代码。为什么在发布之前不尝试一下?
  • @musefan 请注意,这不仅仅是一个是否存在歧义的问题,而是将选择哪个重载的问题。您确实需要做更多工作才能看到它编译的if,您需要确定编译器认为哪个重载是“最好的”。也就是说,这仍然是一件简单的事情。它只是意味着您需要在编译后运行一次。
  • @Servy:是的,在发布后我只是想到了一篇我不久前读过的“优先”文章。我想这会有话要说
  • 我知道它会正确编译,我只是不确定是否有人知道它是否会选择正确的方法。不幸的是,这是 Web 服务的一部分,在测试它之前我还有很长的路要走。不过感谢 cmets。

标签: c# interface overloading


【解决方案1】:

这取决于您如何调用方法。

例如,假设您有Email : IEmailSpecialEmail : ISpecialEmail。如果您声明了电子邮件列表:

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

然后跑了

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

它将为 both 调用 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)

【讨论】:

  • 目标是使用工厂获取电子邮件并简单地运行 emailProcessor.ProcessEmail 方法。那么你将如何执行多态性呢?
  • @Mike 让ProcessEmail 成为IEmail 的方法,或者在该信息中拥有足够的信息来处理任一类型,然后让不同的实现以不同的方式重载接口成员以实现不同的行为。
  • 要使多态性起作用,您需要将 ProcessEmail() 签名移动到 IEmail 的一部分,然后在电子邮件/扩展电子邮件类中进行具体实现。但是,这意味着处理电子邮件的代码将位于您可能不想要的电子邮件对象中 - @Servy 所说的:)
【解决方案2】:

根据 C# 规范(第 7.4.3 节)

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

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

【讨论】:

    猜你喜欢
    • 2013-08-01
    • 2019-06-21
    • 2018-01-13
    • 1970-01-01
    • 2011-10-09
    • 2011-10-23
    • 1970-01-01
    • 2013-09-06
    • 2012-04-25
    相关资源
    最近更新 更多