执行通用接口子类型

Dun*_*Luk 4 .net c# generics inheritance interface

我有一个通用接口(MyInterface<T>),它由ChildA以下示例中的类实现:

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

class ChildA : MyInterface<ChildA>
{
    // Irrelevant:
    MyObj<ChildA> GetObj() {
        return new MyObj<ChildA>();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我需要确保<T>始终具有实现类的类型,因此在这种情况下T应该始终是类型ChildA,因为它是由实现的ChildA.

另一个正确的实现可能是这样的,例如:

class ChildB : MyInterface<ChildB> { ... }
Run Code Online (Sandbox Code Playgroud)

但目前,这种不正确的实现也是可能的,但它不应该是:

class ChildA : MyInterface<ChildB> { ... }
Run Code Online (Sandbox Code Playgroud)

有没有办法强制执行此操作?

Dmy*_*nko 7

您不能强制将泛型类型参数约束为实现类型.

可用的类型约束如下:

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

where T : self在C#中没有任何东西.实际上,它甚至没有意义,因为这样的事情不能有意义地执行.此外,它根本不适合协方差/逆变概念,一般来说,遗传是很奇怪的.

你能做的最接近的事是:

public interface IMyInterface<T> where T : IMyInterface<T>
{
    MyObj<T> GetObj();
}
Run Code Online (Sandbox Code Playgroud)

为什么它没有意义

假设您可以这样做:

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

现在所有实现类型都必须使用自己作为类型参数.但你仍然可以这样做:

public class ChildC<T> : IMyInterface<T> where T : self
{
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

哪个会绕过你的限制.