如何在 C# 中对列表列表使用多态性

问题描述

我在 C# 中将多态性与 int 列表一起使用时遇到问题。我需要“外部”列表才能添加/删除“内部”列表,但“内部”列表不需要更改。所以我考虑使用变量类型ICollection<IEnumerable<int>>。 现在,我现在知道这有效:

IEnumerable<int> someList = new List<int>(); //Works fine

现在我也知道这有效:

ICollection<int> anotherList = new List<int>(); //Also works fine

然而,我惊讶地发现这会引发编译错误

ICollection<IEnumerable<int>> listofLists = new List<List<int>>(); //Doesn't compile

不能隐式转换类型 'System.Collections.Generic.List' 到 'System.Collections.Generic.ICollection'。 存在显式转换(您是否缺少强制转换?)

而且我也惊讶地发现它编译得很好:

IEnumerable<ICollection<int>> anotherlistofLists = new List<List<int>>(); //Works fine (?)

我知道一个简单的 List<List<int>> listofListsWithoutpolymorphism = new List<List<int>>(); 会起作用,但我的问题是:

  1. 第三个和第四个例子有什么区别?
  2. 如何使用多态实现我需要的东西(比如 ICollecion<IEnumerable<int>>)?

解决方法

这与实际接口variance有关,而不是variance >接口实现。

让我们刷新一下:

  • 协方差允许方法具有比接口的泛型类型参数定义的返回类型更派生的返回类型

  • 相反,不变的接口不允许更多派生的类型

示例中的接口签名:

public interface IEnumerable<out T> : IEnumerable {}

public interface ICollection<T> : IEnumerable<T> {}

让我们用一个人为的例子更容易理解:

public interface ICovariant<out T> { }

public interface IInvariant<T> : ICovariant<T> { }

public class SomeClass<T> : IInvariant<T> { }

测试

// works because `SomeClass` implements IInvariant,type parameters are the same
IInvariant<int> test1 = new SomeClass<int>(); 

// works because SomeClass implements IInvariant which implements ICovariant,type parameters are the same
ICovariant<int> test2 = new SomeClass<int>();

// works because SomeClass implements IInvariant,type parameters are the same
IInvariant<ICovariant<int>> test3 = new SomeClass<ICovariant<int>>();

// works because IInvariant implements ICovariant,type parameters are the same
ICovariant<IInvariant<int>> test4 = new SomeClass<IInvariant<int>>();

// works because ICovariant is covariant and SomeClass implements IInvariant
// remembering Covariance permits a more derived type 
ICovariant<IInvariant<int>> test6 = new SomeClass<SomeClass<int>>();

// hold up,this does not work
// IInvariant is invariant and the type parameters are different!
// an Invariant interface doesn't allow a more derived type
IInvariant<ICovariant<int>> test5 = new SomeClass<SomeClass<int>>();

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...