C#匹配模板化方法的签名,以便在派生类中进行覆盖

时间:2018-10-23 21:27:05

标签: c# templates generics override

编辑: 我已经收到一些评论,将其标识为重复项,并链接到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)':找不到合适的方法来覆盖。

有人知道我能做到这一点吗?

谢谢, 伊桑

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

不可能(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();
    }
}

(您可以在ReportService.SetStatus中添加'async'和'await',但是在不知道如何实现代码的情况下,我无法说出它是否很有用)