C# 8中泛型与可空引用类型处理的行为不一致

4

我有这段代码:

public T? Foo<T>()
    where T : class?
{
    return null;
}

出现一个逻辑上可以预期的错误:

可空类型参数必须是值类型或非可空引用类型。考虑添加'class'、'struct'或类型约束。

现在我添加了一个约束条件:

public T? Foo<T>()
    where T : class?, IDisposable // Could be any interface I guess
{
    return null;
}

有趣的是,错误刚好消失了。不过在我看来,我们似乎存在着冲突的限制条件,因为接口是non-nullableclass?不是。

我是否遗漏了什么或编译器存在问题?


你需要 IDisposable?。是的,这很令人困惑。 - canton7
你看过这个吗?-> https://dev59.com/7lMI5IYBdhLWcg3wir-J - panoskarajohn
1
如果至少有一个约束条件是非空的,那么整个约束条件似乎都是非空的。 - Ilya Chernomordik
你确定它消失了吗?我仍然在收到它。 - panoskarajohn
是的,例如,如果您正在制定T既是int又是int?的约束条件,则T必须始终为非空,因为这是符合两个要求的唯一方式。 - Robert McKee
显示剩余2条评论
1个回答

5
通用类型约束where T : IDisposable表示“T必须是非空的并且必须实现IDisposable”。如果您有多个具有不同nullability的通用类型约束,则只有所有约束都可为null时,整体约束才可以为空。
因此,class?是可空的事实被IDisposable不可空的事实所覆盖。
您需要where T : class?, IDisposable?

谢谢你的回答,看起来它是这样工作的,但实际上并不明显,有点令人困惑。我还尝试了使用这样的约束返回可空类型,但那并不起作用:https://stackoverflow.com/questions/59631460/c-sharp-8-gives-a-warning-when-returning-a-nullable-generic-with-nullable-constr - Ilya Chernomordik
同意,我也觉得这很不明显和令人困惑。而且很容易被遗忘! - canton7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接