views:

295

answers:

4

I would like to specify a constraint which is another type with a generic argument.

class KeyFrame<T>
{
    public float Time;
    public T Value;
}

// I want any kind of Keyframe to be accepted
class Timeline<T> where T : Keyframe<*>
{
}

But this cannot be done in c# as of yet, (and I really doubt it will ever be). Is there any elegant solution to this rather than having to specify the type of the keyframe argument?:

class Timeline<TKeyframe, TKeyframeValue> 
     where TKeyframe : Keyframe<TKeyframeValue>,
{
}
+2  A: 

As TimeLine is most likely an aggregation of KeyFrames, wouldn't something like:

class TimeLine<T>
{
private IList<KeyFrame<T>> keyFrameList;
...
}

fulfill your requirements nicely?

workmad3
Wouldn't you at least do an IList (or similar interface) to not hamstring the consumer too much.
WaldenL
Was just doing some throwaway code and C# isn't my most familiar language. Chances are that an IList would be better :)
workmad3
Yes, that was exactly my first implementation but it did not fulfill my requirements as you said. Thanks :)
Trap
A: 

If the type T that Timeline<T> represents is the same as the type KeyFrame<T> represents you can just go with:

class Timeline<T>
{
  List<KeyFrame<T>> _frames = new List<KeyFrame<T>>(); //Or whatever...

  ...
}

If type T represents something different between the classes that implies that Timeline<T> can contain multiple types of KeyFrame's in which case you should create a more abstract implementation of KeyFrame and use that in Timeline<T>.

akmad
+2  A: 

Read about this from Eric Lippert's blog Basically, you have to find a way to refer to the type you want without specifying the secondary type parameter.

In his post, he shows this example as a possible solution:

public abstract class FooBase
{
  private FooBase() {} // Not inheritable by anyone else
  public class Foo<U> : FooBase {...generic stuff ...}

  ... nongeneric stuff ...
}

public class Bar<T> where T: FooBase { ... }
...
new Bar<FooBase.Foo<string>>()

Hope that helps, Troy

Troy Howard
Thanks for the reading. I think the FooBase approach is quite elegant and never thought of it. :)
Trap
A: 

Maybe nesting Timeline inside KeyFrame would make sense in your design:

class KeyFrame<T> { 
  public float Time; 
  public T Value; 

  class Timeline<U> where U : Keyframe<T> { 
  } 
} 
Jordão