为什么我不能将List 作为参数传递给接受List 的方法?

以下代码给出了这个错误:

无法从’System.Collections.Generic.List’转换为’System.Collections.Generic.List’。

如何向编译器指示Customer确实从对象inheritance? 或者它只是没有使用generics集合对象inheritance(发送List会得到相同的错误)。

 using System.Collections.Generic; using System.Windows; using System.Windows.Documents; namespace TestControl3423 { public partial class Window2 : Window { public Window2() { InitializeComponent(); List customers = Customer.GetCustomers(); FillSmartGrid(customers); //List corporateCustomers = CorporateCustomer.GetCorporateCustomers(); //FillSmartGrid(corporateCustomers); } public void FillSmartGrid(List items) { //do reflection on items and display dynamically } } public class Customer { public string FirstName { get; set; } public string LastName { get; set; } public string Street { get; set; } public string Location { get; set; } public string ZipCode { get; set; } public static List GetCustomers() { List customers = new List(); customers.Add(new Customer { FirstName = "Jim", LastName = "Jones", ZipCode = "23434" }); customers.Add(new Customer { FirstName = "Joe", LastName = "Adams", ZipCode = "12312" }); customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson", ZipCode = "23111" }); customers.Add(new Customer { FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" }); customers.Add(new Customer { FirstName = "Jean", LastName = "Anderson", ZipCode = "16623" }); return customers; } } } 

.NET没有协方差和反差(尚未)。

B从A派生并不意味着List派生自List 。 它没有。 它们是两种完全不同的类型。

.NET 4.0将获得有限的协方差和反差异。

这是协方差的问题,并不像第一眼看上去那么容易。 C#4会对此有所支持。

为了解问题,想象一下你的情况下这个演员实际上是有效的。 现在你有一个List ,例如它也有一个Add方法。 但是,实际Add的参数必须是Customer ,因此这显然违反了实现; 该实现不提供Add(object obj)方法。

不幸的是,一些问题本来可以通过使用接口的智能(呃)设计来解决,其中协方差是可以的,例如GetEnumerator。

C#(目前)不支持generics类型的方差。

但是,如果您使用的是C#3.0,则可以执行以下操作:

 FillSmartGrid( customers.Cast() ); 

这是因为类的列表不能转换为基类列表。 这是一个刻意决定使语言安全。 这个问题经常被问到。

以下是我如何解决问题的标准答案:

 List listOfA = new List().ConvertAll(x => (A)x); 

要么:

 List listOfA = new List().Cast().ToList(); 

此外,Eric Lippert本人也是一个很好的解释,他是C#团队的首席架构师之一。

在许多其他答案中,这已被掩盖了。 简短的回答是这样的:

考虑我有这些变量:

 List customers = new List(); //ok, seems fair List objects = new List(); // again, everything's fine 

现在,这里停止编译:

 objects = customers; // sounds OK, since a Customer is an object, right? objects.Add("foo"); 

这有意义吗?

C#4.0将引入有限的能力来执行您正在尝试的操作,但是能够完全按照您的描述执行(将List分配给List将不会被允许用于上面概述的相同推理)。 有关更多信息,请参阅Eric Lippert的博客 ,并更正有关互联网的一些错误信息。

为了解决上面的注释,没有理由不能像在object上那样对Customer实例执行相同的reflection操作。

你可以不是简单地传递一个对象引用然后获取列表类型,而不是传递不适用于上述原因的List,有点像……

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Customer { public int id; public string name; } class Monkey { public void AcceptsObject(object list) { if (list is List) { List customerlist = list as List; foreach (Customer c in customerlist) { Console.WriteLine(c.name); } } } } class Program { static void Main(string[] args) { Monkey monkey = new Monkey(); List customers = new List { new Customer() { id = 1, name = "Fred" } }; monkey.AcceptsObject(customers); Console.ReadLine(); } } } 

为什么参数不能是IList类型?

public void FillSmartGrid(IList项目)

我同意温斯顿史密斯的回答。

我只想指出作为替代方法(虽然这可能不是处理这种情况的最佳方法),而List不是从List派生的,Customer []确实派生自Object []。

因此,可以这样做:

  { List customers = new List(); // ... FillSmartGrid(customers.ToArray()); // ... } public void FillSmartGrid(object[] items) { } 

当然,缺点是你正在创建一个数组对象,所以你可以将它传递给这个函数。