The following is contrived, but bear with me:
interface Clonable<TSubClass>
{
TSubClass Clone();
}
How can I restrict TSubClass to be of the implementing type?
i.e only let the implementor do this:
class Dog : Clonable<Dog>
{
Dog Clone()
{
....
}
}
Not this:
class BadDog : Clonable<Rabbit>
{
Rabbit Clone()
{
....
}
}
You can't enforce that at compile-time, because .NET generics don't have template specialization or duck typing.
You can, however, include a static constructor (type initializer) that uses reflection to assert the relationship at load time. Ok, C# doesn't allow you to put a static constructor on an interface (even though .NET does allow it), so you would need to use a module initializer or a function you call yourself. Also, you would need to search for types implementing the interface, including types that aren't loaded yet (you can subscribe to the Assembly.Load
event to be notified of types loaded in the future).
You can't enforce that, only through convention and documentation....
The convention for me would be to use something like TSelf
.
interface ICloneable<TSelf> where TSelf : ICloneable<TSelf> { ... }
Also note that any non-concrete construct that implements or inherits this interface should pass the constraint through...
[Serializable]
abstract class SerializableCloneable<TSelf> : ICloneable<TSelf>
where TSelf : SerializableCloneable<TSelf> { ... }
Note: I've implemented this check in NRoles using the convention of calling your self-type parameter S
.
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