代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

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

  •  12
  • Edward Tanguay  · 技术社区  · 15 年前

    以下代码给出了此错误:

    无法从转换 'System.Collections.Generic.List' 到

    如何向编译器指出客户确实从对象继承? 或者它只是不继承泛型集合对象(发送 List<string> 获取相同的错误)。

    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;
            }
        }
    }
    
    8 回复  |  直到 15 年前
        1
  •  14
  •   Mark Seemann    15 年前

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

    B源于A并不意味着 List<B> List<A>

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

        2
  •  8
  •   Lucero    15 年前

    这就是协方差的问题,它并不像乍一看那么容易。C4将得到一些支持。

    要了解这些问题,请想象一下,在您的案例中,该演员阵容将真正发挥作用。现在你有一个 List<object> ,例如,它还有一个 Add 添加 一定是个 Customer ,明显违反了执行;该实现没有提供 Add(object obj)

    不幸的是,通过使用智能(er)接口设计和协方差正常的通用方法(如GetEnumerator),可以解决一些问题。

        3
  •  7
  •   Winston Smith    15 年前

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

    FillSmartGrid( customers.Cast<object>() );
    
        4
  •  6
  •   Community CDub    8 年前

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

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

    或:

    List<A> listOfA = new List<C>().Cast<A>().ToList();
    

    阿尔索 here

        5
  •  2
  •   Adam Robinson    15 年前

    这一点在许多其他答案中都有提及。简单的回答是:

    假设我有这些变量:

    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"); 
    

    现在这有意义吗?

    确切地 如您所述(分配一个 List<Customer> List<object> 不允许使用与我上面概述的相同的推理)。看见 Eric Lippert's blog 有关更多信息,以及对互联网上流传的一些错误信息的更正。

    Customer 尽可能在 object .

        6
  •  1
  •   Dan Hedges    15 年前

    除了传递由于上述原因不起作用的列表,您是否可以不只是传递一个对象引用,然后再获取列表类型,有点像。。。

    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();
            }
        }
    }
    
        7
  •  0
  •   ScottE    15 年前

    公共空白填充SmartGrid(IList项)

        8
  •  0
  •   Dr. Wily's Apprentice    15 年前

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

    List<Customer> 不是源于 List<Object> ,客户[]不从对象[]派生。

    因此,可以这样做:

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

    当然,缺点是创建数组对象只是为了将其传递给此函数。