【问题标题】:Why can't I instantiate List<Object> with List<Tuple<string, bool>>? [duplicate]为什么我不能用 List<Tuple<string, bool>> 实例化 List<Object>? [复制]
【发布时间】:2015-08-14 23:15:43
【问题描述】:

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

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

基于某些标志,我想这样做:

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

这样我几乎可以使用myList,而无需对使用列表的方法进行太多更改。在大多数情况下,它们只会将元素添加到列表中而不是从中读取,因此这种“hack”会相当方便。

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

【问题讨论】:

    标签: c# list casting tuples


    【解决方案1】:

    List&lt;T&gt; 不是covariant type

    如果是这样,一个问题是类可能根据其分配的泛型类型以不同的方式运行。例如,想象一下:

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

    现在,如果您允许将Foo&lt;string&gt; 转换为Foo&lt;object&gt;,那么FooBar() 在转换后会返回什么?

    有三种解决方案:

    1. 只需使用List&lt;object&gt; 并向其中添加Tuple&lt;string, bool&gt; 类型实例即可。
    2. 转换为IList。不过,这有潜在的缺点,因为您期望 List&lt;T&gt; 和实现 IList不同 类可能会被传递。
    3. 将您接受的列表类型转换为层次结构并使用基本类型的列表,例如:

    .

    abstract class Animal { }
    
    class Cat : Animal { }
    class Dog : Animal { }
    
    public List<Animal> animals = new List<Animal>();
    

    然后你可以以CatDog对象为参数调用.Add()和其他方法,用is检查每个条目的类型,完全避免强制转换。不过,这是否合适取决于您的类型以及它们之间的交互方式。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2014-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多