Yakitawa
Yakitawa

Reputation: 169

Generic type specified by inherits

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

Answers (4)

leofun01
leofun01

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

Uladz
Uladz

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

Michael Gunter
Michael Gunter

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

Kitson88
Kitson88

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

Related Questions