
AI
为什么你不能执行 List
csharpinterface IFoo{ void Bar();}class Bar : IFoo{ public void Bar() { Console.WriteLine("Bar"); }}class Program{ static void MAIn(string[] args) { List<IFoo> foo = new List<Bar>(); foo.Add(new Bar()); }}在上面的代码中,我们定义了一个接口 IFoo,其中包含一个方法 Bar()。然后我们创建了一个类 Bar,它实现了接口 IFoo 中的方法。接下来,我们在 MAIn 方法中创建了一个 List 类型的变量 foo,并将其初始化为一个 List 类型的实例。最后,我们将一个 Bar 类型的实例添加到了 foo 列表中。尽管我们可以将一个 Bar 类型的实例赋值给 IFoo 类型的变量,但是我们不能将一个 List 类型的实例赋值给 List 类型的变量。这是因为 C# 中的泛型类型不支持协变(Covariance)。什么是协变(Covariance)?协变是指在类型转换中,如果派生类型可以隐式转换为基类型,那么这个类型就是协变的。在C#中,协变支持的最常见的情况就是数组类型的协变。考虑以下的代码示例:csharpBar[] bars = new Bar[] { new Bar() };IFoo[] foos = bars;在上面的代码中,我们创建了一个 Bar 类型的数组 bars,并将其赋值给一个 IFoo 类型的数组 foos。这是因为数组类型是协变的,即我们可以将一个派生类型的数组赋值给基类型的数组。然而,泛型类型不支持协变。这是因为泛型类型的类型参数是在编译时确定的,而不是在运行时确定的。在上面的代码中,List 和 List 实际上是两种不同的类型,即使 Bar 类型实现了 IFoo 接口。因此,我们不能将一个 List 类型的实例赋值给 List 类型的变量。如何解决这个问题?为了解决这个问题,我们可以使用接口的泛型版本来实现协变。在 C# 4.0 中引入的协变特性允许我们在接口的泛型参数前加上 out 关键字来声明协变。考虑以下的代码示例:csharpinterface IFoo<out T>{ void Bar();}class Bar : IFoo<Bar>{ public void Bar() { Console.WriteLine("Bar"); }}class Program{ static void MAIn(string[] args) { List<IFoo<Bar>> foo = new List<Bar>(); foo.Add(new Bar()); }}在上面的代码中,我们定义了一个泛型接口 IFoo,其中的 out 关键字表示该接口是协变的。我们还修改了 List 的类型为 List> ,这样就可以将一个 List 类型的实例赋值给 List> 类型的变量。这样我们就可以将 Bar 类型的实例添加到 foo 列表中了。在C#中,我们不能将一个 List 类型的实例赋值给 List 类型的变量。这是因为泛型类型不支持协变。为了解决这个问题,我们可以使用接口的泛型版本来实现协变。通过使用协变特性,我们可以将一个派生类型的实例赋值给基类型的接口泛型参数。这样我们就可以在泛型集合中存储不同类型的对象,并以统一的方式对它们进行操作。Copyright © 2025 IZhiDa.com All Rights Reserved.
知答 版权所有 粤ICP备2023042255号