【问题标题】:C# Matching a Templated Method's Signature in order to override in a Derived ClassC# 匹配模板化方法的签名以便在派生类中覆盖
【发布时间】:2019-03-28 05:23:31
【问题描述】:

编辑: 我收到了一些 cmets 将其识别为重复并链接到 virtual、override 和其他此类关键字的定义,但这不是我正在寻找的完整答案。我在原始帖子中声明我尝试使用 virtual 和 override 关键字但出现编译器错误。我最初从代码中省略了这些关键字,因为它没有编译,但我现在将它们放入以将问题集中在派生类的方法签名不匹配到足以覆盖基类的方法这一事实上.简单地添加这些关键字并不能解决我的问题。在阅读了我收到的回复后,我意识到我需要帮助来编译代码并实现我正在寻找的结果。


您好,我的代码看起来很像:

// WeeklyReport.cs
public class WeeklyReport: Report {
    // class definitions
}

// ReportService.cs
public class ReportService
{
    public async Task<ResponseMessage> ChangeStatus<T>(string reportId, string status) where T:Report, new()
    {
         var report = await SelectReportById<T>(reportId);
         // do stuff
         return await SetStatus(change, report);
    }

    public virtual async Task<ResponseMessage> SetStatus<T>(StatusChange change, T report) where T : Report, new()
    {
        // do stuff
    }
}

// WeeklyReportService.cs
public class WeeklyReportService : ReportService
{
    // This method does not compile!!!
    public override async Task<ResponseMessage> SetStatus(StatusChange change, WeeklyReport report)
    {
        // do stuff
    }
}

以上代码的简短说明:

我有两个模型类,Report 和 WeeklyReport。 WeeklyReport 是 Report 的子类

我有两个服务类,ReportService 和 WeeklyReportService。 WeeklyReportService 是 ReportService 的子类,并试图覆盖其 SetStatus() 方法

问题:

当我在 WeeklyReportService 的实例上调用 ChangeStatus() 时。我希望调用 WeeklyReportService 中定义的 SetStatus(),而不是 ReportService 中定义的 SetStatus()。

我已经尝试将 virtual 和 override 关键字添加到方法签名中,但我得到 'WeeklyReportService.SetStatus(StatusChange change, WeeklyReport report)':没有找到合适的方法来覆盖。

有谁知道我如何做到这一点?

谢谢, 伊森

【问题讨论】:

标签: c# templates generics overriding


【解决方案1】:

这里发生了一些小的概念混淆。 C# 中没有泛型的模板(特化)。您可以使用完全相同的签名覆盖虚拟方法,但您不能提供将根据类型自动选择和运行的特定于类型的实现。

在这里,您将使用参数类型 T 进行覆盖,但您的派生实现(与基类不同,知道 WeeklyReport 存在)将检查类型,转换为 WeeklyReport 并调用特定于类型的重载(而不是覆盖)。

这听起来像是一个抽象的 ReportService,其中 T 是 Report 和派生的 WeeklyReportService:ReportService。

【讨论】:

  • 感谢您解释为什么该函数没有被覆盖!
【解决方案2】:

不可能 (AFAIK) 完全按照您的意愿行事,但您应该能够做到:

public class WeeklyReportService : ReportService
{
    public override Task<ResponseMessage> SetStatus<T>(StatusChange change, T report) where T : Report, new()
    {
        if (report is WeeklyReport weeklyReport)
            return SetWeeklyReportStatus(change, weeklyReport);
        return super.SetStatus(change, report);
    }
    async Task<ResponseMessage> SetWeeklyReportStatus(StatusChange change, WeeklyReport report)
    {
        report.Status = change;
        await report.SaveChanges(); // or whatever
        return MakeResponseMessage();
    }
}

(您可以将“async”和“await”添加到 ReportService.SetStatus,但在不了解您的代码可能如何实现的情况下,我不能说它是否有用)

【讨论】:

  • 感谢您的回答!这个确切的修复会为我完成它,除非我收到一个错误,说我必须升级到 c# 7.1 才能使用该语法。事实证明,我们仍然在 7.0 上,此时升级对我来说不是一个选择(大型代码库,测试人员不愿意为这个故事做完全回归)。我最终完全按照您所说的那样覆盖了 SetStatus() 方法,并使用了一个辅助函数,除了我让辅助方法采用动态而不是 WeeklyReport 作为类型,然后我只是在第一行将其类型转换为一种解决方法,直到我们升级。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 2018-06-06
  • 1970-01-01
  • 1970-01-01
  • 2017-06-22
相关资源
最近更新 更多