【问题标题】:C#: No casting within Generics?C#:在泛型中没有强制转换?
【发布时间】:2009-04-19 13:18:00
【问题描述】:

虽然我可以将字符串向上转换为对象,但我不能将字符串的 IList 向上转换为对象的 IList。怎么会?除了将所有项目处理到新的 IList 之外,现在还能做什么?

static void ThisWorks()
{
     IList<object> list = new List<object>();
     list.Add("I can add a string since string : object");
}

static void ThisDoesNotWork()
{
     // throws an invalid cast exception
     IList<object> list = (IList<object>) new List<string>(); 

     list.Add("I'm never getting here ... why?");
}

【问题讨论】:

    标签: c# generics casting


    【解决方案1】:

    这是不可能的,因为泛型是不变的(从 C# 3.0 开始)。

    您可以使用以下方法解决它:

    var objectList = list.Cast<object>().ToList();
    

    【讨论】:

    • 我想你的意思是说泛型不变的。它们不是协变的。不过,它们将使用 C# 4。
    • @John:即使在 C# 4 中,也只有某些东西是协变的。特别是,类不能是变体——只能是委托和接口。
    • 乔恩:这是我的错。我错误地写了“不是不变的”,而约翰在句子中指出了那个错误:)
    • @Jon:你是对的。但在这种情况下,您可以将 List 视为 IList 并获得相同的效果。他想要的一般操作(将更多派生条目添加到派生较少的列表中)现在是合法的。
    【解决方案2】:

    这样看:虽然香蕉是水果,但一篮子香蕉不是一篮子水果,因为您可以在后者中添加橙子,但不能在前者中添加橙子。您的 List&lt;string&gt;List&lt;object&gt; 具有更强的约束。

    选角应该始终尊重Liskow。对于不允许修改的容器和迭代器,这样的转换是安全的,但是一旦事情可以改变,你就如履薄冰。

    【讨论】:

    • 这确实尊重 LSP:他将 more 派生类型(字符串)视为 less 派生类型(对象)。一般来说,这应该是安全的。
    • 不。他正试图用香蕉篮做一个水果篮。只要他只做读取是安全的,但如果添加非字符串,事情就会变得奇怪。
    • 事实上,这在某些情况下是可能的——比如支持 safe 泛型 co/contravariance 的 C# 4.0,所以你的例子并不完全正确。
    • 此外,自 Microsoft .NET Framework 的第一个版本以来,数组就支持变体。您可以将 Orange[] 转换为 Fruit[]。
    • @Pontus:这就是重点。从类型理论的角度来看,将一篮子香蕉视为一篮子水果的行为很好。它不应该导致异常,但它确实是因为泛型是不变的。
    【解决方案3】:

    你问的本质上是逆变和协方差的问题。它是编程语言设计中的一个概念,它讨论方法和集合如何针对同一继承层次结构中的两个类的对象进行行为。阅读Wikipedia article 可能有助于将您的上述好奇心放在一个更大、更普遍的角度。

    【讨论】:

      【解决方案4】:

      string 继承自 objectIList&lt;string&gt; 不继承自 IList&lt;object&gt; 它们是不相关的类型,因此您不能在它们之间进行转换。

      试想一下如果这行得通会发生什么:

      // THIS CODE DOES NOT WORK
      IList<object> list = new List<string>(); // this doesn't compile
      list.Add(5); // because this is perfectly valid on IList<object> but not on IList<string>
      

      【讨论】:

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