gpt4 book ai didi

C# 嵌套泛型在使用约束时区别对待

转载 作者:行者123 更新时间:2023-11-30 15:39:36 25 4
gpt4 key购买 nike

使用嵌套泛型时,直接使用时编译器会失败,但使用约束时编译器会正确编译。

例子:

public static void Test1<V, E>(this Dictionary<V, E> dict)
where V : IVertex
where E : IEdge<V>
{}

public static void Test2(this Dictionary<IVertex, IEdge<IVertex>> dict){}

上面的两个扩展方法表面上具有相同的签名,但如果我现在尝试运行如下代码:

var dict = new Dictionary<VertexInstance, EdgeInstance>();

dict.Test1();
dict.Test2();

编译器会在“Test2”上出错,指出它无法转换为具有内联嵌套泛型的泛型形式。我个人觉得 Test2 的语法更直观。

我最初将此作为一个问题的答案发布,该问题询问使用通用约束和直接使用接口(interface)之间的区别,但我很好奇为什么会发生这种情况?

最佳答案

扩展我的评论:

这些扩展方法当然没有相同的签名。 Dictionary<IVertex, IEdge<IVertex>>Dictionary<VertexInstance, EdgeInstance> 不同. @Payo 是正确的;这是一个方差问题。类不能是协变或逆变的。接口(interface)可以,但前提是它们被标记为它,并且 IDictionary 不能被标记为它,因为它不安全,因此更改为 IDictionary 在这里无济于事。

考虑这是否被允许。您的 Test2 实现可能如下所示:

public static void Test2(this Dictionary<IVertex, IEdge<IVertex>> dict)
{
dict.Add(new EvilVertex(), new EvilEdge());
}

EvilVertex 和 EvilEdge 可以实现正确的接口(interface),但不能继承自 VertexInstance 和 EdgeInstance。然后调用将在运行时失败。因此,对 Test2 的调用无法证明是安全的,因此编译器不允许这样做。

Thank you for the answer; however, the constraints version could have the same code inside and would have the same issue, wouldn't it?

不!约束版本内部可能具有相同的代码,因为您无法从 EvilVertex 进行转换至 V , 也不来自 EvilEdgeE .您可以强制从类型强制转换为类型参数,首先转换为 object ,但这当然会在运行时失败。

Also, why is variance controlled at that level?

因为泛型的一个目的是在编译时证明代码的类型安全。

Your dict.Add should have the compilation error not the extension method in my view.

如前所述,对 dict Add 的调用通用版本的编译器错误。它不可能是接口(interface)版本的编译器错误,因为在 Test2 的上下文中,您所知道的是您正在将 EvilVertex 转换为 IVertex,这是完全合法的。

关于C# 嵌套泛型在使用约束时区别对待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10181289/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com