In C# I sometimes wish I could make special methods for certain "instantiations" of generic classes.
UPDATE: The following code is just a dumb example of a more abstract problem - don't focus too much on time series, just the principles of "adding extra methods" for certain T.
Example:
class Timeseries<T>
{
...
TimeSeries<T> Slice(...) { ... }
}
In the case where T is double, I would like some extra methods, like Integrate()
, Interpolate()
and so on that make only sense for double
, because I need to do arithmetic on them.
There are several ways to do this, but I cannot find one that I'm satisfied with.
1. Inherit into a special class
class TimeseriesDouble : Timeseries<double>
{
double Interpolate(...) { ... }
...
}
cons: TimeseriesDouble.Slice()
will return a new Timeseries<double>
object, now missing my special methods.
2. External methods
public static double Interpolate(Timeseries<double> ts, ...) { ... }
cons: Breaks with OO principles. And I don't want to put my methods away. Also, the methods might need private/protected state.
3. Extension methods
Same as 2, just with a nicer calling syntax.
4. Common base class
class TimeSeries_base { ... }
class TimeSeries<T> : TimeSeries_base { .. typesafe versions of methods .. }
class TimeSeriesDouble : TimeSeries_base { .. typesafe versions of methods .. }
cons: too much duplication of things from TimeSeries_base
into the two subclasses. The base class might become just a place holder for utility functions for the sub classes.
pro: I can now do things like List<TimeSeries_base>
dynamically.
5. Just forget about a common class
I.e., keep Timeseries<T>
and TimeseriesDouble
separate in the code.
cons: Then I don't get all the benefit of treating a TimeseriesDouble
like a TimeSeries<T>
, e.g. combining two timeseries with ZIP(A,B), where one happens to be of doubles.
Any other ideas? Currently, I think I like the design (1) best.
The declaration of a generic class is almost the same as that of a non-generic class except the class name is followed by a type parameter section. The type parameter section of a generic class can have one or more type parameters separated by commas.
The generic class works with multiple data types. A normal class works with only one kind of data type.
Generic is a class which allows the user to define classes and methods with the placeholder. Generics were added to version 2.0 of the C# language. The basic idea behind using Generic is to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes, and interfaces.
You cannot inherit a generic type. // class Derived20 : T {}// NO!
You could always use the self-referential generics trick:
public class TimeSeries<T, U> where U : TimeSeries<T, U>
{
U Slice(...)
}
public class TimeSeriesDouble : TimeSeries<double, TimeSeriesDouble>
{
...
}
It can get a bit brain-bending, but it can work.
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() { ... }
}
I would go with (1) and cast as appropriate.
TimeSeriesDouble tsD = new TimeSeriesDouble();
TimeSeriesDouble subTSD = tsD.Slice(...) as TimeSeriesDouble;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With