gpt4 book ai didi

c# - 为什么协变类型参数仅用于成员的返回类型?

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

为什么协变类型参数像 IEnumerable<out T>类型T仅用于返回类型(只读)或逆逆变类型参数,如 Action<in T>类型T仅用作参数类型(只写)?换句话说,我认为纯协变概念和仅用于成员的返回类型的 C# 协变类型参数之间存在关系。

最佳答案

Why do covariant type parameters like IEnumerable<out T> have type T used only for the return type?

首先:T必须仅用于返回类型。例如:

interface I1<out T>{ T M1(); }
interface I2<out T>{ void M2(Action<I1<T>> a); }

I1<T> , T仅用于返回类型位置。但在 I2 , T用于输入 a ,以及 I1<T>Action 的输入,所以从某种意义上说,它在这里被用于两个输入位置。

但是让我们考虑一个更简单的情况。为什么我们可以做I1 T 中的协变但在 T 中不逆变?

原因是协变是安全的而逆变则不然。我们可以看到协方差是安全的:

class Animal {}
class Mammal : Animal {}
class Tiger : Mammal {}
class Giraffe : Mammal {}
class C : I1<Mammal> {
public Mammal M1() { return new Tiger(); }
}
I1<Mammal> i1m = new C(); // Legal
I1<Animal> i1a = i1m; // Legal
Animal a = i1a.M1(); // Returns a tiger; assigned to animal, good!

无论如何C.M1返回,它始终是 Mammal因此总是 Animal .

但这不合法:

I1<Giraffe> i1g = i1m; // Not legal
Giraffe g = i1g.M1(); // Returns a tiger; assigned to giraffe, bad!

第一行必须是非法的,这样第二行就永远不会执行。

现在您应该有足够的信息来弄清楚为什么逆变会这样工作。请记住,您始终可以回到一个简单的示例并问自己“如果这是合法的,我以后会犯什么错误?”类型系统正在保护您不犯这些错误!

练习:对 I2<T> 进行同样的分析。您知道为什么使用 T 是合法的吗?在两个个输入位置,即使它是 out 。 (提示:Action 是逆变的,因此它反转了赋值兼容性的方向。如果反转方向两次会发生什么?)

关于c# - 为什么协变类型参数仅用于成员的返回类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50813330/

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