在 C# 中,协变和逆变分别是指什么?它们通常用于哪些场景,并能带来什么好处?
考察说明
考查候选人是否理解 C# 中泛型类型参数的协变与逆变概念及其实际用途。
回答思路
- 【回答框架 1】协变(covariance)是指允许将使用派生类型(更具体类型)的对象分配给使用基类型(更抽象类型)的变量,例如将 IEnumerable<string> 视为 IEnumerable<object>。逆变(contravariance)则相反,允许将使用基类型的对象分配给使用派生类型的变量,例如将 Action<object> 视为 Action<string>。
- 【回答框架 2】在 C# 中,这些行为通常通过泛型接口或委托上的 out 和 in 关键字来实现。out 关键字用于协变,表示类型参数只能用作返回值;in 关键字用于逆变,表示类型参数只能用作输入参数。例如,IEnumerable<out T> 支持协变,而 Action<in T> 支持逆变。
- 【回答框架 3】协变和逆变的主要好处是提高了泛型类型在赋值和类型转换时的灵活性,使得代码可以更自然地遵循面向对象的多态原则。例如,一个返回 IEnumerable<string> 的方法可以直接赋值给 IEnumerable<object> 类型的变量,无需显式转换。
- 【回答框架 4】在 C# 中,协变和逆变仅适用于泛型接口和委托,不适用于类或结构体。此外,它们不影响引用类型的运行时实际类型,只影响编译时的类型转换,并且对于值类型不生效。
- 【关键点 1】协变使用 out 关键字,逆变使用 in 关键字。
- 【关键点 2】协变允许将派生类型视为基类型,逆变允许将基类型视为派生类型。
- 【关键点 3】协变和逆变仅适用于泛型接口和委托,不适用于类。
- 【易错点 1】混淆协变和逆变的适用场景,例如错误地将 in 用于返回值。
- 【易错点 2】忘记协变和逆变不支持值类型,导致编译错误。
- 【易错点 3】误以为协变和逆变会改变对象的实际类型,实际上只影响编译时类型转换。