覆盖非泛型类的泛型方法

时间:2017-09-21 18:35:05

标签: c# generics override generic-method

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

第一个代码块显示了一个使用泛型类创建抽象方法的简单示例,该方法返回比基类中约束的接口更具体的接口。

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

现在,如果从Chart类中删除泛型类型但保留泛型方法的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();
    }
}

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

如果抽象和虚拟关键字基本上不支持这种情况,我希望在创建抽象泛型方法时会出错。如果你不能在这里使用语法来避免在其他代码中进行转换,那么如何正确使用抽象泛型方法呢? (我甚至无法将T转换为ISeries--看起来约束在子类中丢失,好像它不知道T必须是一个ISeries)

请注意,此处问题的目的是了解不解决此问题的方法或提出不同的“解决方案”。

3 个答案:

答案 0 :(得分:0)

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

假设您执行以下代码

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

根据GetSeries的签名,这将是有效的代码,但是,如果可比,您编写的方法会将Series<float>放入Series<int>类型的变量中这就是为什么{在返回return new Series<float>();

的方法中不允许使用{1}}

答案 1 :(得分:0)

当您使用泛型方法时,这意味着您不知道该def user_logged_in_handler(sender,request,user, **kwargs): UserSession.objects.get_or_create( user= user, session_id= request.session.session_key ) user_logged_in.connect(user_logged_in_handler, sender=CustomUser) 参数的具体类型。

那你如何判断它是T

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

Series<float>

这会导致出现错误,因为在内部您尝试返回var ac = new AnalogChart(); Series<int> series = ac.GetSeries<Series<int>>();

您对泛型类的初步尝试似乎是一种更好的方法。

顺便说一下,你可以“欺骗”编译器让它通过,但这不是一个好主意,除非你绝对确定这将是Series<float>的类型(即使那时我也会选择不同的策略):

T

答案 2 :(得分:-2)

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

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

如果您有Chart或IChart变量,则允许获取ISeries,但如果您具有更具体的类型,则允许检索更具体的接口。不幸的是,看起来我不能覆盖抽象,同时使它成为新的,所以我在使用抛出的抽象类中使用虚方法。

我想使用相同的方法名称,虽然我也可以创建&#39; GetPhasorSeries&#39;,&#39; GetTimeSeries&#39;相反的方法,但我真的想挖掘并实现这个特定的结果。

我试图以一种他们没有设计的方式来修饰泛型。 虽然我仍然不确定为什么你会创建一个抽象或虚拟的通用方法。我仍然欢迎任何关于什么模式使用这个结构的想法(考虑到这个问题的所有上下文) )。