I'm building the following class:
abstract class Foo
{
protected abstract void Process(FooProcessor<T> processor)
}
What I need is to make T
be the type of child Foo
class:
class FooChild : Foo
{
protected override void Process(FooProcessor<FooChild> processor)
{
}
}
Is it achievable? If so, how?
A generic type is a generic class or interface that is parameterized over types. The following Box class will be modified to demonstrate the concept.
Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on.
The question mark ( ? ) wildcard character can be used to represent an unknown type using generic code. Wildcards can be used with parameters, fields, local variables, and return types.
Something like a self-constraint will allow you to expose derived types and also constrain at the same time:
abstract class Foo<T> where T : Foo<T>
{
protected abstract void Process(FooProcessor<T> processor);
}
Then derived types define themselves as the target:
class FooChild : Foo<FooChild>
{
protected override void Process(FooProcessor<FooChild> processor)
{
}
}
Please note though that this design tends to only have a small set of uses. Also, you lose the ability to refer to Foo
as a base without specifying it's generic type.
There is also a blog post from Eric Lippert about how it is possible to abuse this design, so you might want to consider what it is you are actually trying to achieve by wanting to have your protected method reference the derived class directly.
You may be better off using interfaces to encapsulate the behaviour you are trying to achieve.
You mean this:
class FooProcessor<T>
{
}
abstract class Foo<T>
{
protected abstract void Process(FooProcessor<T> processor);
}
class FooChild : Foo<FooChild>
{
protected override void Process(FooProcessor<FooChild> processor)
{
}
}
It would be easier to implement with an interface:
interface FooProcessor<T>
{
}
interface Foo<T>
{
void Process(FooProcessor<T> processor);
}
class FooChild : Foo<FooChild>
{
void Foo<FooChild>.Process(FooProcessor<FooChild> processor)
{
this.Process((FooProcessorFooChild)processor);
}
protected void Process(FooProcessorFooChild processor)
{
}
}
class FooProcessorFooChild : FooProcessor<FooChild>
{
}
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