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

前端 未结 8 413
北恋
北恋 2021-01-11 13:31

The following code gives me this error:

Cannot convert from \'System.Collections.Generic.List\' to \'System.Collections.Generic.List\'.

相关标签:
8条回答
  • 2021-01-11 13:44

    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...

    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();
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-11 13:50

    .NET does not have co-variance and contra-variance (yet).

    That B derives from A doesn't imply that List<B> derives from List<A>. It doesn't. They are two totally different types.

    .NET 4.0 will get limited co-variance and contra-variance.

    0 讨论(0)
  • 2021-01-11 13:50

    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.

    0 讨论(0)
  • 2021-01-11 13:56

    C# (at present) does not support variance for generic types.

    However, if you're using C# 3.0, you can do this:

    FillSmartGrid( customers.Cast<object>() );
    
    0 讨论(0)
  • 2021-01-11 13:59

    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[].

    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.

    0 讨论(0)
  • 2021-01-11 14:05

    Why can't the parameter be of type IList?

    public void FillSmartGrid(IList items)

    0 讨论(0)
提交回复
热议问题