以下代码给出了这个错误:
无法转换 'System.Collections.Generic.List' 至 'System.Collections.Generic.List'。
如何向编译器指出Customer确实从对象继承?或者它是否仅使用泛型集合对象进行继承(发送List<string>
会得到相同的错误)。< / p>
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
namespace TestControl3423
{
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
List<Customer> customers = Customer.GetCustomers();
FillSmartGrid(customers);
//List<CorporateCustomer> corporateCustomers = CorporateCustomer.GetCorporateCustomers();
//FillSmartGrid(corporateCustomers);
}
public void FillSmartGrid(List<object> 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<Customer> GetCustomers()
{
List<Customer> customers = new List<Customer>();
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;
}
}
}
答案 0 :(得分:14)
.NET没有协方差和反差(尚未)。
B来自A并不意味着List<B>
来自List<A>
。它没有。它们是两种完全不同的类型。
.NET 4.0将获得有限的协方差和反差异。
答案 1 :(得分:8)
这就是协方差的问题,并不像第一眼看上去那么容易。 C#4会对此有所支持。
为了了解问题,想象一下你的情况下这个演员实际上是有效的。现在你有一个List<object>
,例如它也有一个Add
方法。但是,实际Add
的参数必须是Customer
,因此这显然违反了实施;该实现不提供Add(object obj)
方法。
不幸的是,一些问题可以通过使用通用方法的接口的智能(呃)设计来解决,其中协方差是可以的,例如对于GetEnumerator。
答案 2 :(得分:7)
C#(目前)不支持泛型类型的差异。
但是,如果您使用的是C#3.0,则可以执行此操作:
FillSmartGrid( customers.Cast<object>() );
答案 3 :(得分:6)
这是因为类的列表不能转换为基类列表。这是一个刻意决定使语言安全。这个问题经常被问到。
Here是我如何解决这个问题的标准答案:
List<A> listOfA = new List<C>().ConvertAll(x => (A)x);
或:
List<A> listOfA = new List<C>().Cast<A>().ToList();
同样here是Eric Lippert本人的一个很好的解释,他是C#团队的首席架构师之一。
答案 4 :(得分:2)
在许多其他答案中,这已经被令人厌恶。简短的回答是:
考虑我有这些变量:
List<Customer> customers = new List<Customer>(); //ok, seems fair
List<object> objects = new List<object>(); // again, everything's fine
现在,这是停止编译的地方:
objects = customers; // sounds OK, since a Customer is an object, right?
objects.Add("foo");
这现在有意义吗?
C#4.0会引入有限的能力来执行您正在尝试的内容,但能够按照您的描述完全(将List<Customer>
分配给List<object>
赢得'允许我在上面概述的相同推理。有关详细信息,请参阅Eric Lippert's blog,以及对互联网周围的一些错误信息进行更正。
要解决上述评论,您无法在Customer
实例上执行与object
上相同的反思操作。
答案 5 :(得分:1)
不是传递由于上述原因而无效的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<Customer>) {
List<Customer> customerlist = list as List<Customer>;
foreach (Customer c in customerlist) {
Console.WriteLine(c.name);
}
}
}
}
class Program {
static void Main(string[] args) {
Monkey monkey = new Monkey();
List<Customer> customers = new List<Customer> { new Customer() { id = 1, name = "Fred" } };
monkey.AcceptsObject(customers);
Console.ReadLine();
}
}
}
答案 6 :(得分:0)
为什么参数不能是IList类型?
public void FillSmartGrid(IList项目)
答案 7 :(得分:0)
我同意温斯顿史密斯的回答。
我只是想指出作为替代方案(尽管这可能不是处理这种情况的最佳方式),虽然List<Customer>
不是来自List<Object>
,但客户[]确实来自对象[]。
因此,可以这样做:
{
List<Customer> customers = new List<Customer>();
// ...
FillSmartGrid(customers.ToArray());
// ...
}
public void FillSmartGrid(object[] items)
{
}
当然,缺点是你正在创建一个数组对象,所以你可以把它传递给这个函数。