Reputation: 169
I do not think what I want is possible, but I hope someone can verify this and maybe explain why it is impossible.
We have an inheritance of Bar<T>
, for which we cannot touch the source code of Bar<T>
abstract class Foo<T> : Bar<T>
We offer Foo<T>
to be implemented by a third party, and we also want to dictate that whatever class inherits from Foo<T>
is the specified type for T
.
This can of course be done manually by the third party, for instance
class Fizz : Foo<Fizz>
However, I find the repetition of Fizz
cumbersome and ugly.
Is it possible to have Foo<T>
automatically use Fizz
as the specified type for T
?
In other words, is it possible to let Foo<T>
be implemented something along these lines
abstract class Foo : Bar<T>
where T : "Whatever class inherits from Foo"
... which I do not believe is possible because I cannot find a fitting generic type constraint. Is it possible to do something like this instead
[SomeBlackMagic("Dear compiler, T is whatever inherits from Foo.")]
abstract class Foo : Bar<T>
... such that an implementation of Fizz
could simply be
class Fizz : Foo
Upvotes: 4
Views: 86
Reputation: 235
abstract class Foo<T> : Bar<T>
where T : Foo<T>
{ /* ... */ }
class Fizz : Foo<Fizz>
{ /* ... */ }
I know it's not what you're looking for, but it's best choice.
Upvotes: 0
Reputation: 1968
We also want to dictate that whatever class inherits from Foo is the specified type for T.
This requirement may be implemented as a custom Roslyn analyzer.
While this piece abstract class Foo : Bar<T>
is unfortunately impossible, cause T
generic parameter should be closed by some type or Foo
must be generic as well.
Upvotes: 2
Reputation: 12811
This is what's known as the Curiously Recurring Template Pattern. Unfortunately, most strongly-typed languages have no way of removing this code smell. C# has no way to improve upon this.
You could resort to runtime checks, but at the expense of compile-time checking. Also, you wouldn't actually get to use the type in your class interface. For example, you wouldn't be able to do something like abstract class Foo<T> { public T Bar() { ... } }
because T
wouldn't be known by the compiler.
Upvotes: 2
Reputation: 2940
This might not be what your looking for, but have you considered implementing an interface onto Foo<T>
so you can always be sure what type the generic T
will be?
public class Bar<T>
{}
public interface IDev
{}
public abstract class Foo<T> : Bar<T> where T : IDev
{}
public class Fizz : Foo<Fizz>, IDev
{}
It would give you some control over the generic object being passed in.
Upvotes: 2