接口成员中定义的可空引用类型在实现中不需要为可空的原因是什么?

What is the reason why nullable reference types defined in interface members aren't required to be nullable in the implementations?

从 C# 8.0 开始,我可以这样做:

interface IMyInterface
{
#nullable enable
    void DoSomething(string? withValue);
#nullable disable
}

即使用可为空的引用类型参数 string? withValue,但是当我实现接口时,这是完全合法的——实际上,当 VS 中的工具自动生成实现代码时,结果如下:

class MyImpl : IMyInterface
{
    public void DoSomething(string withValue)
    {
        throw new NotImplementedException();
    }
}

我特别希望实现需要 withValue 参数的可空引用类型,那么为什么不需要呢?能够在接口中定义可为空的引用类型参数有什么意义?

why isn't it required?

这不是必需的,因为当您编译接口的实现时,您没有启用可为空的引用类型。

当未启用可空引用类型检查时,关于可空引用类型的任何内容都不会生效。您明确表示,在未启用它的代码上下文中,您不希望编译器提供可空引用类型的编译时强制执行。

所以,事实并非如此。就好像类型的可空性根本不存在一样。

What is the point of being able to define a nullable reference type argument in an interface?

出于同样的原因,您可以为任何方法定义可为空的引用类型参数。为了表明,当启用可空引用类型检查时,调用者可以传递 null 作为参数的值。

这样一来,如果您在启用可为空引用类型检查的上下文中编译实现或使用该接口的代码,您 收到关于类型不正确的预期警告匹配执行。这反过来应该让您意识到您的实现规定参数必须是非空的,而实际上,当通过接口而不是直接在实现中调用成员时,代码可以传递空值。

请注意,仅当使用不可为 null 的引用类型声明实现并且使用可为 null 的引用类型声明接口时才会出现警告,因为这是唯一危险的组合。当接口声明为不可为空且实现声明为可为空时,这是非常安全的,不会发出警告。

接口的作者不一定知道在实现甚至使用接口时是否启用可空引用类型检查。因此,当然可能存在参数的可空性并不重要的情况。但是当可空引用类型检查有用时,即启用时,它的每一点都与可空引用类型一样有用。

这就是能够在接口中定义可为 null 的引用类型参数的意义所在。