Typing variables holding instances of constrained generic classes
I am just starting to get to grips with generics and am (ab)using them to refactor a fairly complex section of my code (I've only been using c# for a little while but am fairly experienced in other languages).
I have an inheritance structure where my classes extend a base class. In the base class I have most of the functionality implemented. But I want to be able to associate these children classes with instances of their siblings.
Here is a simplification of some of the relevant code:
class ParentClass<T>
where T : ParentClass<T>, new()
{
public static T Create()
{
return new T();
}
private object joinedItem;
public void Join<TJoinee>(TJoinee item)
where TJoinee : ParentClass<TJoinee>, new()
{
joinedItem = item;
}
}
class ChildOne : ParentClass<ChildOne>
{
}
class ChildTwo : ParentClass<ChildTwo>
{
}
With this code in place I can do something like:
var a = ChildOne.Create();
a.Join(new ChildTwo());
The problem is that I needed to type joinedItem
as ob开发者_如何学Cject when really I want to type it as ParentClass<Something>
. Is it possible to prescribe a more specific type to joinedItem
? Or am I just horribly abusing the language and should be taking a completely different approach?
Could you extract an interface from ParentClass<T>
that is not dependent on T
? That way joinedItem
could be typed to the interface.
That seems to be as far as you can take what it looks like you're trying to do (join ParentClass<T>
instances to ParentClass<U>
instances).
If there is nothing in that ParentClass<T>
interface that is not dependant on T
, then it will be difficult to find a more useful interface than object without knowing T
.
The core issue here is that it is not possible to express the notion that a variable must be of type XYZ<_>
- with arbitrary type parameter.
You can express that in parameters, then you just need to add constraints (as you do), but you cannot to that to variables (at least, not without adding the variable type to the list of type parameters, which is likely to be syntactically ugly).
So, if you need to express the notion of XYZ<_>
for any type _
you will need to represent that notion explicitly as a type (say IXYZ
), and ensure that all XYZ<_> : IXYZ
's actually inherit from that. Generally, the most flexible way to do that is via an interface, but an abstract base class would work too.
Unfortunately, type classes in general aren't part of generics ;-).
精彩评论