为什么我无法用List<Tuple<string, bool>>实例化List<Object>?

3

这可能是相当明显的,但我似乎无法理解。对于一个相当复杂的重构(也称为hack),我需要能够根据一些标志交换列表的“类型”。为了使交换更容易并防止嵌套函数的“下游”更改,我决定像这样做:

List<Object> myList = new List<Tuple<string, bool>>();

基于特定的标志,我希望做出如下更改:

List<Object> myList= new List<MyObject>();

这样我就可以几乎不用修改消耗列表的方法,就能使用myList。在大多数情况下,它们只会向列表中添加元素而不会从中读取,因此这种“hack”将非常方便。

然而,我似乎无法做到这一点,因为C#编译器抱怨无法从System.Tuple转换为Object。我真正缺少什么?

2个回答

4

List<T>不是一个协变类型

如果是协变类型,那么其中一个问题是,类可能会根据其分配的泛型类型而表现出不同的行为。例如,想象一下:

class Foo<T>
{
    public bool FooBar()
    {
        return typeof(T).Name.ToLower() == "object";
    }
}

现在,如果允许将Foo<string>强制转换为Foo<object>,那么在转换后FooBar()返回什么?
有三种解决方案:
1. 只需使用List<object>并向其中添加Tuple<string,bool>类型的实例即可。 2. 强制转换为IList。但这可能会带来潜在的缺点,因为您期望的是一个List<T>,而可能会传递一个实现了IList但是不同的类。 3. 将接受的列表类型转换为层次结构并使用基本类型的列表,例如:
abstract class Animal { }

class Cat : Animal { }
class Dog : Animal { }

public List<Animal> animals = new List<Animal>();

然后,您可以使用 CatDog 对象作为参数调用 .Add() 等方法,使用 is 检查每个条目的类型,并完全避免转换。但是,是否适合取决于您的类型及其相互作用。


1

List<T>不是协变的。你不能这样做。如果你想要,可以创建一个List<object>,并用所有元素填充它。虽然我真的看不出使用带有object的强类型泛型列表的优势。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接