在非泛型上覆盖泛型方法 class

Overriding a generic method on a non generic class

我知道如何使用通用 class 来实现我的目标。但是要理解为什么在非泛型 class 中允许泛型方法的语法(声明为虚拟或抽象),我似乎无法确定。

第一段代码展示了一个简单示例,它使用泛型 class 创建一个抽象方法,该方法 returns 比基础 class 中限制的接口更具体。

public interface ISeries
{
    string Name { get; set; }
    string Color { get; set; }
}
public interface ITimeSeries<TY> : ISeries
{
    double[] XValues { get; set; }
    TY[] YValues { get; set; }
}

public interface IPhasorSeries : ISeries
{
    double Magnitude { get; }
    double Angle { get; }
}
public class PhasorSeries : IPhasorSeries
{
    public string Name { get; set; }
    public string Color { get; set; }
    public double Magnitude { get; set; }
    public double Angle { get; set; }
}
public class Series<T> : ITimeSeries<T>
{
    public string Name { get; set; }
    public string Color { get; set; }
    public double[] XValues { get; set; }
    public T[] YValues { get; set; }
}
public abstract class Chart<T> where T : ISeries
{
    public abstract T GetSeries();
}

public class AnalogChart : Chart<ISeries>
{
    public override ISeries GetSeries()
    {
        return new Series<float>();
    }
}

public class PhasorChart : Chart<IPhasorSeries>
{
    public override IPhasorSeries GetSeries()
    {
        return new PhasorSeries();
    }
}

现在,如果从图表中删除泛型类型 class 但保留具有 ISeries 约束的泛型方法,我会得到以下错误。

public abstract class Chart
{
    public abstract T GetSeries<T>() where T : ISeries;
}

public class AnalogChart : Chart
{
    public override T GetSeries<T>()
    {
        // ERROR:
        // Cannot implicitly convert type Test.Series<float> to 'T'
        // Cannot convert expression type Test.Series<float> to return type 'T'
        return new Series<float>();
    }
}

public class PhasorChart : Chart
{
    public override T GetSeries<T>()
    {
        // ERROR:
        // Cannot implicitly convert type Test.PhasorSeries to 'T'
        // Cannot convert expression type Test.PhasorSeries to return type 'T'
        return new PhasorSeries();
    }
}

看来我不完全理解在非泛型 class 中实现泛型方法时发生了什么。当使用通用 class 时——存在多个 class 定义。当你只有一个泛型方法时,这意味着什么?实际上有多种方法吗?或者它只是以某种方式调用相同的方法?

如果 abstract 和 virtual 关键字基本上不支持这一点,我本以为在创建抽象泛型方法时会出现错误。如果您不能使用此处的语法来避免在其他代码中进行强制转换,那么如何正确使用抽象泛型方法。 (我什至无法将 T 转换为 ISeries——似乎约束在 subclass 中丢失,就好像它不知道 T 必须是 ISeries)

请注意,此处问题的目的是了解正在发生的事情,无法解决此问题或提出不同的 'solutions'。

当您的 return 类型是 T 时,您必须 return 一个 T 无论 T 是什么。您不能 return 具有硬编码类型的对象并希望它是 T。

假设您执行以下代码

Series<int> intSeries = angloChart.GetSeries<Series<int>>();

根据 GetSeries 的签名,那将是有效代码,但是,如果可比较,您编写的方法会将 Series<float> 放入类型 Series<int> 的变量中 那是为什么在 return 是 T

的方法中不允许 return new Series<float>();

当您使用泛型方法时,意味着您不知道该 T 参数的具体类型。

那么你如何确定它是 Series<float>

是什么阻止我像这样调用此方法:

var ac = new AnalogChart();
Series<int> series = ac.GetSeries<Series<int>>();

这会导致转换错误,因为在内部您正在尝试 return Series<float>

您最初尝试使用通用 类 似乎是更好的方法。

顺便说一句,你可以 "trick" 编译器让它通过,但这不是一个好主意,除非你绝对确定这将是 T 的类型(并且即使那样我也会选择不同的策略):

return (T)(object) new Series<float>();

为了达到预期的结果,我意识到我可以使用显式接口实现并避免一起使用泛型。

public interface IChart
{
    ISeries GetSeries();
}
public abtract class Chart : IChart
{
    public virtual ISeries GetSeries()
    {
        throw new NotImplementedException();
    }
}

public class AnalogChart : Chart, IChart
{
    public new ITimeSeries<float> GetSeries()
    {
        return new Series<float>();
    }

    ISeries IChart.GetSeries()
    {
        return GetSeries();
    }
}

public class PhasorChart : Chart, IChart
{
    public new IPhasorSeries GetSeries()
    {
        return new PhasorSeries();
    }
    ISeries IChart.GetSeries()
    {
        return GetSeries();
    }
}

如果您有图表或 IChart 变量,这允许获取一个 ISeries,但如果您有更具体的类型,则允许检索更具体的接口。不幸的是,看起来我无法在更新抽象时覆盖它,所以我被困在抽象 class 中使用虚拟方法抛出。

我想使用相同的方法名称,尽管我也可以只创建 'GetPhasorSeries'、'GetTimeSeries' 方法,但我真的很想深入研究并实现这个特定结果。

我试图以一种非设计的方式改变泛型。 尽管我仍然不确定您为什么要创建一个抽象或虚拟的泛型方法。我仍然欢迎任何关于什么模式使用此构造的想法(鉴于此的所有上下文)问题)。