在非泛型上覆盖泛型方法 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' 方法,但我真的很想深入研究并实现这个特定结果。
我试图以一种非设计的方式改变泛型。 尽管我仍然不确定您为什么要创建一个抽象或虚拟的泛型方法。我仍然欢迎任何关于什么模式使用此构造的想法(鉴于此的所有上下文)问题)。
我知道如何使用通用 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' 方法,但我真的很想深入研究并实现这个特定结果。
我试图以一种非设计的方式改变泛型。 尽管我仍然不确定您为什么要创建一个抽象或虚拟的泛型方法。我仍然欢迎任何关于什么模式使用此构造的想法(鉴于此的所有上下文)问题)。