泛型的协方差/转换问题

时间:2012-10-24 17:03:10

标签: c# generics

考虑代码:

using System.Collections.Generic;
namespace TestingTypes
{
    class Program
    {
        static void Main(string[] args)
        {
            var strings = new List<string>();               
            INeedToPassThisMethodAListOfObjects(strings as List<object>);
        }

        static void INeedToPassThisMethodAListOfObjects(List<object> objects) { }
    }
}

1>------ Build started: Project: TestingTypes, Configuration: Debug Any CPU ------
1>c:\users\[censored]\TestingTypes\Program.cs(9,41,9,64): error CS0039: Cannot convert 
type 'System.Collections.Generic.List<string>' to 
'System.Collections.Generic.List<object>' via a reference conversion, boxing 
conversion, unboxing conversion, wrapping conversion, or null type conversion

你可能会说List&lt; string&gt; List&lt; object&gt;,因为字符串是一个对象,C#4应该支持泛型类型的协方差。

  • 为什么编译器说它无法转换类型?
  • 如何将“字符串”传递给方法?

3 个答案:

答案 0 :(得分:3)

您收到错误是因为List<string>不是List<object>

您可以在list.Add(new TextBox())上致电List<object>,但很明显,同一通话对List<string>无效。

如果泛型类型是不可变的,那么C#泛型只允许Covariance(这是我从List到IEnumerable的转换)。

如果您需要将列表传递给方法,可以尝试传递

listOfStrings.Cast<object>();

缺点是,如果使用该解决方案,对方法调用内的列表所做的任何修改都不会反映在原始列表中(因为对Cast的调用会创建一个新列表)。

如果您控制方法INeedToPassThisMethodAListOfObjects并且该方法只需要迭代集合而不是修改它,您可以将参数类型更改为IEnumerable<object>,在这种情况下您只需要能够毫无问题地通过你的List<string>

答案 1 :(得分:3)

接口可以是变体;班级不能。 See here for the explanation.

如果您未通过strings集合并将声明更改为

,则您的代码将有效
static void INeedToPassThisMethodAListOfObjects(IEnumerable<object> objects) { }

但是,这取决于您是否需要此功能中的List

答案 2 :(得分:2)

您必须将字符串转换为对象。这是一个很好的LINQ方法。

var strings = new List<string>();               
INeedToPassThisMethodAListOfObjects(strings.Cast<object>());

修改

根据您自己的链接,

  

在C#中,以下情况支持方差:

     
      
  • 数组中的协方差(自C#1.0起)

  •   
  • 代表中的协方差和逆变,也称为“方法组差异”(自C#2.0起)

  •   
  • 接口和代理中的泛型类型参数的差异(自C#4.0起)

  •   

所以IEnumerable会接受List