Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforcing generic interface childs type

I have a generic interface (MyInterface<T>), which is implemented by the class ChildA in the example below:

public interface MyInterface<T>
{
    MyObj<T> GetObj(); // Irrelevant
}

class ChildA : MyInterface<ChildA>
{
    // Irrelevant:
    MyObj<ChildA> GetObj() {
        return new MyObj<ChildA>();
    }
}

This works, but I need to make sure that <T> always has the type of the implementing class, so in this case T should always be of type ChildA, because it is implemented by ChildA.

Another correct implementation could be this, for example:

class ChildB : MyInterface<ChildB> { ... }

But currently, this incorrect implementation is also possible, while it should not be:

class ChildA : MyInterface<ChildB> { ... }

Is there a way to enforce this?

like image 326
Duncan Luk Avatar asked Dec 19 '22 14:12

Duncan Luk


1 Answers

You cannot enforce a generic type argument to be constrained to the implementing type.

The available type constraints are the following:

  • where T : struct
  • where T : class
  • where T : new()
  • where T : <base class name>
  • where T : <interface name>
  • where T : U

There is nothing like where T : self in C#. Actually, it wouldn't even make sense, because such a thing cannot be meaningfully enforced. Besides, it wouldn't fit at all into the covariance/contravariance concepts and would be weird to inherit from, in general.

The closest thing you can do is this:

public interface IMyInterface<T> where T : IMyInterface<T>
{
    MyObj<T> GetObj();
}

Why it wouldn't make sense

Let's say you could do this:

public interface IMyInterface<T> where T : self // this syntax does not exist in C#
{
    MyObj<T> GetObj();
}

Now all implementing types would have to use themselves as the type argument. But you could still do this:

public class ChildC<T> : IMyInterface<T> where T : self
{
    /* ... */
}

Which would go around your restriction.

like image 119
Dmytro Shevchenko Avatar answered Dec 21 '22 05:12

Dmytro Shevchenko