为什么我不能将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; } } }
这是协方差的问题,并不像第一眼看上去那么容易。 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 = 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) { }
当然,缺点是你正在创建一个数组对象,所以你可以将它传递给这个函数。