接口中的类型约束适用于基类

pok*_*oke 6 c# generics type-constraints

我有一个基类定义了这样的泛型方法:

public class BaseClass
{
    public T DoSomething<T> ()
    { ... }
}
Run Code Online (Sandbox Code Playgroud)

由于这个类是由第三方提供的,并没有附带接口,因此我定义了一个接口,用于定义该类中实际需要的方法.这样我就可以得到松散的耦合,并且实际上可以用其他东西来交换第三方类.对于此示例,请考虑以下接口:

public interface ISomething
{
    T DoSomething<T> ()
        where T : Foo;
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它定义了相同的方法,但也对类型参数应用了类型约束,该类型参数来自与此无关的其他一些要求.

接下来,我定义了一个BaseClass也实现的子类型ISomething.该类将用作接口背后的通常实现 - 而接口将是应用程序的其余部分将访问的内容.

public class Something : BaseClass, ISomething
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

因为DoSomethingin BaseClass已经支持任何类型参数T,所以它应该特别支持一个类型参数,它是一个子类型Foo.所以人们会期望BaseClass已经实现了接口的子类型.但是我收到以下错误:

方法'BaseClass.DoSomething()'的类型参数'T'的约束必须匹配接口方法'ISomething.DoSomething()'的类型参数'T'的约束.请考虑使用显式接口实现.

现在,我有两种可能性; 第一个是做错误建议并明确地实现接口.第二种是使用new以下方法隐藏基本实现:

// Explicit implementation
T ISomething.DoSomething<T> ()
{
    return base.DoSomething<T>();
}

// Method hiding
public new T DoSomething<T>()
    where T : Foo
{
    return base.DoSomething<T>();
}
Run Code Online (Sandbox Code Playgroud)

两者都有效,虽然我可能更喜欢第二种解决方案,以保持方法可以从类本身访问.但是它仍然留下以下问题:

当基类型使用less-strict(read:none)类型约束实现它时,为什么必须重新实现该方法?为什么该方法需要完全按原样实现?

编辑:为了给方法更多的意义,我将返回类型从更改voidT.在我的实际应用程序中,我有泛型参数和返回值.

Jon*_*Jon 1

当然,给定的代码可以安全地编译和运行:

Something实例类型为 asSomething或 as 时BaseClass,编译器将允许任何类型 for T,而当同一实例类型为 as 时,编译ISomething器将只允许类型继承Foo。在这两种情况下,您都可以像往常一样获得静态检查和运行时安全性。

事实上,上面的场景正是式实现时所发生的情况ISomething因此,让我们看看我们可以对当前的事态提出哪些支持和反对的论据。

为了:

  • 拟议的解决方案并不适用于所有情况;它取决于确切的方法签名(类型参数是协变的吗?逆变的?不变的?)
  • 它不需要用新的文本来修改规范,说明如何处理此类情况
  • 它使代码能够自我记录——你不必学习所说的文本;当前关于显式接口实现的规则就足够了
  • 它不会给 C# 编译器团队带来开发成本(文档、功能实现、测试等)

反对:

  • 你需要输入更多内容

考虑到上述情况以及这不是日常情况的事实,恕我直言,要得出的结论很明确:这可能很好,但它肯定不保证你不遗余力地实施它。