在C#中,我有时希望能为泛型类的某些“实例化”创建特殊方法。
更新:以下代码只是一个更抽象问题的愚蠢例子 - 不要过多关注时间序列,只是为某些T“添加额外方法”的原则。 / p>
示例:
class Timeseries<T>
{
...
TimeSeries<T> Slice(...) { ... }
}
在T为double的情况下,我想要一些额外的方法,例如Integrate()
,Interpolate()
等等,只对double
有意义,因为我需要做算术在他们身上。
有几种方法可以做到这一点,但我找不到一个我满意的方法。
1。继承为特殊类
class TimeseriesDouble : Timeseries<double>
{
double Interpolate(...) { ... }
...
}
缺点: TimeseriesDouble.Slice()
会返回一个新的Timeseries<double>
对象,现在错过了我的特殊方法。
2。外部方法
public static double Interpolate(Timeseries<double> ts, ...) { ... }
缺点:违反OO原则。而且我不想放弃我的方法。此外,这些方法可能需要私有/受保护状态。
第3。扩展方法
与2相同,只是使用更好的调用语法。
4。共同基类
class TimeSeries_base { ... }
class TimeSeries<T> : TimeSeries_base { .. typesafe versions of methods .. }
class TimeSeriesDouble : TimeSeries_base { .. typesafe versions of methods .. }
缺点:从TimeSeries_base
到两个子类的重复过多。基类可能只是子类的实用程序函数的占位符。
亲:我现在可以动态地执行List<TimeSeries_base>
等操作。
5。忘掉一个共同的课程
即,在代码中保持Timeseries<T>
和TimeseriesDouble
分开。
缺点:然后我无法像TimeseriesDouble
一样处理TimeSeries<T>
,例如将两个时间序列与ZIP(A,B)组合在一起,其中一个恰好是双打。
还有其他想法吗? 目前,我认为我最喜欢设计(1)。
答案 0 :(得分:12)
你总是可以使用自引用泛型技巧:
public class TimeSeries<T, U> where U : TimeSeries<T, U>
{
U Slice(...)
}
public class TimeSeriesDouble : TimeSeries<double, TimeSeriesDouble>
{
...
}
它可能有点弯曲,但它可以工作。
答案 1 :(得分:9)
interface ITimeSeries<T> { ... }
abstract class TimeSeriesBase<TS> where TS : TimeSeriesBase<TS>
{ public TS Slice() { ... }
}
class TimeSeries<T>:TimeSeriesBase<TimeSeries<T>>,ITimeSeries<T> {}
class TimeSeriesDouble:TimeSeriesBase<TimeSeriesDouble>,ITimeSeries<double>
{ public double Interpolate() { ... }
}
答案 2 :(得分:1)
我会选择(1)并在适当的时候施展。
TimeSeriesDouble tsD = new TimeSeriesDouble();
TimeSeriesDouble subTSD = tsD.Slice(...) as TimeSeriesDouble;
答案 3 :(得分:0)
我会考虑实现一个工厂来返回适当的子类。