简体   繁体   English

为什么我不能通过 List<Customer> 作为接受 List 的方法的参数<object> ?

[英]Why can't I pass List<Customer> as a parameter to a method that accepts List<object>?

The following code gives me this error:以下代码给了我这个错误:

Cannot convert from 'System.Collections.Generic.List' to 'System.Collections.Generic.List'.无法从“System.Collections.Generic.List”转换为“System.Collections.Generic.List”。

How can I indicate to the compiler that Customer indeed inherits from object?如何向编译器表明 Customer 确实继承自对象? Or does it just not do inheritance with generic collection objects (sending a List<string> gets the same error).或者它只是不使用通用集合对象进行继承(发送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;
        }
    }
}

.NET does not have co-variance and contra-variance (yet). .NET 还没有协方差和逆方差(目前)。

That B derives from A doesn't imply that List<B> derives from List<A> . B 派生自 A 并不意味着List<B>派生自List<A> It doesn't.它没有。 They are two totally different types.它们是完全不同的两种类型。

.NET 4.0 will get limited co-variance and contra-variance. .NET 4.0 将获得有限的协方差和逆方差。

That's the problem of covariance, and it is not as easy as it looks at first sight.这就是协方差的问题,它并不像乍一看那么容易。 C# 4 will have some support for that. C# 4 将对此提供一些支持。

To get the idea of the problems, imagine in your case that this cast would actually work.要了解问题所在,请想象在您的情况下此演员表实际上会起作用。 Now you'h have a List<object> , which for instance also has an Add method.现在你有一个List<object> ,例如它也有一个Add方法。 However, the argument for the actual Add must be a Customer , so that this clearly violates the implementation;但是,实际Add的参数必须是Customer ,因此这显然违反了实现; the implementation does not provide the Add(object obj) method.该实现不提供Add(object obj)方法。

Unfortunately, some issues could have been solved by using a smart(er) design of the interfaces with generic methods where covariance is OK, such as for GetEnumerator.不幸的是,一些问题可以通过使用具有通用方法的接口的智能(更)设计来解决,其中协方差是可以的,例如 GetEnumerator。

C# (at present) does not support variance for generic types. C#(目前)不支持泛型类型的变化。

However, if you're using C# 3.0, you can do this:但是,如果您使用的是 C# 3.0,则可以执行以下操作:

FillSmartGrid( customers.Cast<object>() );

It's because a list of a class is not convertible to a list of the base class.这是因为类的列表不能转换为基类的列表。 It's a deliberate decision to make the language safe.使语言安全是一个深思熟虑的决定。 This question gets asked often.这个问题经常被问到。

Here is my standard answer of how to work around the issue: 是我如何解决这个问题的标准答案:

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

or:要么:

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

Also here is really good explanation from Eric Lippert himself, one of the chief architects on the C# team.此外,C# 团队的首席架构师之一 Eric Lippert 本人也给出很好的解释。

This has been covered ad-nauseum in many other answers.这已在许多其他答案中被讨论过。 The short answer is this:简短的回答是这样的:

Consider I have these variables:考虑我有这些变量:

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

Now, here's where it stops compiling:现在,这是它停止编译的地方:

objects = customers; // sounds OK, since a Customer is an object, right?

objects.Add("foo"); 

Does that make sense now?这现在有意义吗?

C# 4.0 will introduce limited ability to do what you're attempting, though being able to do exactly as you describe (assign a List<Customer> to a List<object> won't be allowed for the same reasoning I outlined above). C# 4.0 将引入有限的能力来做你正在尝试的事情,尽管能够完全按照你的描述做(由于我上面概述的同样的原因,不允许将List<Customer>分配给List<object> )。 See Eric Lippert's blog for more information, and a correction to some misinformation that's going around the interwebs.请参阅Eric Lippert 的博客以获取更多信息,并纠正一些在互联网上流传的错误信息。

To address your comment above, there's no reason that you can't perform the same reflection operations on a Customer instance as you can on an object .为了解决您上面的评论,您没有理由不能在Customer实例上执行与在object上相同的反射操作。

Instead of passing List which does not work for the reasons above, could you not simply pass just an object reference then get the list type afterwards, kinda like...除了传递由于上述原因而不起作用的 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();
        }
    }
}

Why can't the parameter be of type IList?为什么参数不能是 IList 类型?

public void FillSmartGrid(IList items) public void FillSmartGrid(IList 项)

I agree with Winston Smith's answer.我同意温斯顿史密斯的回答。

I just wanted to point out as an alternative (although this possibly isn't the best way to handle the situation) that while List<Customer> does not derive from List<Object> , Customer[] does derive from Object[].我只是想指出作为替代方案(尽管这可能不是处理这种情况的最佳方法),虽然List<Customer>不是从List<Object>派生的,但 Customer[] 确实是从 Object[] 派生的。

Therefore, it is possible to do this:因此,可以这样做:

    {
        List<Customer> customers = new List<Customer>();
        // ...
        FillSmartGrid(customers.ToArray());
        // ...
    }

    public void FillSmartGrid(object[] items)
    {
    }

Of course, the downside is that you're creating an array object just so you can pass it to this function.当然,缺点是您正在创建一个数组对象,以便您可以将它传递给这个函数。

为什么我不能从列表中投射<myclass>列出<object> ?<div id="text_translate"><p> 我有一个对象列表,它们属于我的QuoteHeader类型,我想将此列表作为对象列表传递给能够接受List&lt;object&gt;的方法。</p><p> 我的代码行显示...</p><pre> Tools.MyMethod((List&lt;object&gt;)MyListOfQuoteHeaders);</pre><p> 但是我在设计时收到以下错误...</p><pre> Cannot convert type 'System.Collections.Generic.List&lt;MyNameSpace.QuoteHeader&gt;' to 'System.Collections.Generic.List&lt;object&gt;'</pre><p> 我需要对我的 class 做任何事情来允许这样做吗? 我认为所有类都继承自 object 所以我不明白为什么这不起作用?</p></div></object></myclass> - Why can't I cast from a List<MyClass> to List<object>?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我不能通过List <T> 一般的构造函数参数虽然满足所有约束? - Why can't I pass List<T> to a generic constructor parameter although all contraints are met? 为什么我不能将此对象添加到此列表中? - Why I can't add this object into this list? 我可以使用List吗? <object> 作为方法中的形式参数? - Can I use List<object> as a formal parameter in a method? 为什么我不能从列表中投射<myclass>列出<object> ?<div id="text_translate"><p> 我有一个对象列表,它们属于我的QuoteHeader类型,我想将此列表作为对象列表传递给能够接受List&lt;object&gt;的方法。</p><p> 我的代码行显示...</p><pre> Tools.MyMethod((List&lt;object&gt;)MyListOfQuoteHeaders);</pre><p> 但是我在设计时收到以下错误...</p><pre> Cannot convert type 'System.Collections.Generic.List&lt;MyNameSpace.QuoteHeader&gt;' to 'System.Collections.Generic.List&lt;object&gt;'</pre><p> 我需要对我的 class 做任何事情来允许这样做吗? 我认为所有类都继承自 object 所以我不明白为什么这不起作用?</p></div></object></myclass> - Why can't I cast from a List<MyClass> to List<object>? 为什么我不能将此对象从视图传递到控制器方法? - Why I can't pass this object from a view to a controller method? 动态传递对象列表作为参数 - Dynamically Pass List of Object As A Parameter 为什么我不能在按钮事件中添加新的List对象 - why can't I add a new List object in button event 传递未知列表<T>作为参数? - Pass unknown List<T> as parameter? 为什么我不能将List <List <Foo >>传递给IEnumerable <IEnumerable <Foo >> - Why can't I pass a List<List<Foo>> to an IEnumerable<IEnumerable<Foo>> 在C#中,为什么我不能将StringReader传递给带有Stream参数的方法? - In C#, why can't I pass a StringReader to a method with a Stream parameter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM