Reputation: 9298
Is this possible? When i compile i get an error saying cannot convert Component to TComponent even with the constraint
public interface IComponent<TKey, TComponent> where TComponent : IComponent<TKey, TComponent>
{
TComponent Parent { get; }
void Register(TKey key, TComponent component);
void RegsiterWith(TKey key, TComponent component);
}
public class Component<TKey, TComponent> : IComponent<TKey, TComponent> where TComponent : IComponent<TKey, TComponent>
{
private TComponent _parent;
public void Register(TKey key, TComponent component)
{
component.RegsiterWith(key, this);
}
public void RegsiterWith(TKey key, TComponent component)
{
component.Register(key, this);
}
public TComponent Parent { get { return _parent; } }
}
Upvotes: 1
Views: 157
Reputation: 1500385
The reason that it fails is because TComponent
could actually be some other implementation of IComponent<TKey, TComponent>
. Just because Component
implements the interface doesn't mean that nothing else can :)
One way round this would be to change the interface:
public interface IComponent<TKey, TComponent>
where TComponent : IComponent<TKey, TComponent>
{
TComponent Parent { get; }
void Register(TKey key, IComponent<TKey, TComponent> component);
void RegsiterWith(TKey key, IComponent<TKey, TComponent> component);
}
Whether that's feasible in your situation I don't know, but it would certainly avoid the type issue.
Another option would be to cast this
as spender suggested. This could fail at execution time, but in reality unless you do create an alternative implementation, it won't. It's slightly annoying, having to cast when using generics, but occasionally it happens.
EDIT: Here's an example of how it could go wrong:
public class Other : IComponent<string, Other>
{
// Implement interface
}
Now what happens if you create a Component<string, Other>
? It satisfies the constraint with no problems... but a Component
isn't an Other
...
Now you could change your constraint like this:
public class Component<TKey, TComponent> : IComponent<TKey, TComponent>
where TComponent : Component<TKey, TComponent>
i.e. constrain TComponent
on Component
instead of IComponent
. That still has issues though:
public class FooComponent : Component<string, FooComponent> {}
public class BarComponent : Component<string, FooComponent> {}
Here, you probably want BarComponent
to have a TComponent
of itself, but it's got a different component. The code you've shown so far will probably be okay, but this sort of quirk may hamper other goals. Worth considering...
Oh, and if you're happy to make Component
sealed, at that point the changed constraint is enough (I think!).
Upvotes: 8
Reputation: 120440
How about a cast:
public void Register(TKey key, TComponent component)
{
component.RegsiterWith(key, (TComponent)this);
}
Upvotes: 0