为什么我不能使用List <tuple <string,bool =“”>&gt;实例化List <object>?

时间:2015-08-14 23:15:43

标签: c# list casting tuples

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

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

基于某些标志我想改为:

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

这样我就可以使用myList,而不会在使用列表的方法中进行太多更改。在大多数情况下,他们只是在列表中添加元素而不是从中读取,因此这种“黑客”会非常方便。

但是,我似乎无法做到这一点,因为C#编译器抱怨它无法从System.Tuple转换为Object。我真的错过了什么?

2 个答案:

答案 0 :(得分:4)

List<T>不是covariant type

如果是这样,一个问题是类可能根据其指定的泛型类型进行不同的操作。例如,想象一下:

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. 将您接受的列表类型转换为层次结构,并使用基本类型列表,例如:
  4. abstract class Animal { }
    
    class Cat : Animal { }
    class Dog : Animal { }
    
    public List<Animal> animals = new List<Animal>();
    

    然后,您可以使用.Add()Cat个对象作为参数调用Dog和其他方法,使用is检查每个条目的类型,并完全避免强制转换。这是否合适取决于您的类型以及它们如何相互作用。

答案 1 :(得分:1)

List<T>不是covariant。你不能这样做。如果需要,创建一个List<object>并用所有元素填充它。虽然我并没有真正看到使用带有object的强类型通用列表的优势。