Force type of child interface types

I have a common interface ( MyInterface<T>) that is implemented by the class ChildAin 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 it <T>always has the type of the implementing class, so in this case Tit should always have the type ChildA, because it is implemented ChildA.

Another option may be correct , 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 any way to provide this?

+4
source share
4

.

:

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

# where T : self. , , . , / .

, , :

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

, :

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

. :

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

.

+7

?

, . , :

public abstract class BaseChild<T> : MyInterface<T>
{
    protected BaseChild()
    {
        if (typeof(T) != this.GetType())
        {
            throw new InvalidOperationException(string.Format(
                          "Type {0} is not supported as valid type parameter for type {1}",
                             typeof(T).Name, this.GetType().Name));
        }
    }
}

:

class ChildA : BaseChild<int> { }

// Bang! throws
var instance = new ChildA(); 

.

class ChildB : BaseChild<ChildB> { }

// Ok here
var instance = new ChildB(); 
+2

You cannot do this, but you can create your own control that compares the general type of interface and the type of your class. See an example:

class ChildA : MyInterface<ChildB>
{
    public ChildA()
    {
        this.ValidateGenericType();
    }

    public MyObj<ChildB> GetObj()
    {
        return new MyObj<ChildB>();
    }

    protected void ValidateGenericType()
    {
        //throws an Exception because ChildB is different of ChilA
        if (this.GetType().Name != this.GetType().GetInterfaces()[0].GetGenericArguments()[0].Name)
        {
            throw new Exception("The generic type must be of type ChildA.");
        }
    }
}
+1
source

It seems that you should use extension methods instead of force use for this interface

public interface ISomeInterface {}

public class Child: ISomeInterface {}

public class OtherChild : ISomeInterface { }

public static class MyInterfaceExtensions
{
    public static MyObj<T> GetMyObj<T>(this T child) where T : ISomeInterface
    {
        return new MyObj<T>();
    }
}

public static class Test
{
    public static void RunTest()
    {
        var child = new Child();
        var otherChild = new OtherChild();

        MyObj<Child> myObj = child.GetMyObj();
        MyObj<OtherChild> myOtherObj = otherChild.GetMyObj();
    }
}
+1
source

Source: https://habr.com/ru/post/1650023/


All Articles