In C#, why can't a List object be stored in a List<object> variable

前端 未结 14 1370
别跟我提以往
别跟我提以往 2020-11-22 03:42

It seems that a List object cannot be stored in a List variable in C#, and can\'t even be explicitly cast that way.

List sl = new List

        
相关标签:
14条回答
  • 2020-11-22 04:31

    This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.

    You might want to try the ff code instead:

    List<string> sl = new List<string>();
    //populate sl
    List<object> ol = new List<object>(sl);
    

    or:

    List<object> ol = new List<object>();
    ol.AddRange(sl);
    

    ol will (theoretically) copy all the contents of sl without problems.

    0 讨论(0)
  • 2020-11-22 04:34

    The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]

    Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.

    That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.

    0 讨论(0)
  • 2020-11-22 04:35

    I think that this (contravariance) will actually be supported in C# 4.0. http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

    0 讨论(0)
  • 2020-11-22 04:40

    Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.

    public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
    {
        List<B> newList = new List<B>();
    
        foreach (D item in list)
        {
            newList.Add(item);
        }
    
        return newList;
    }
    

    (Based on Zooba's example)

    0 讨论(0)
  • 2020-11-22 04:40

    Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:

    IEnumerable<object> ob;
    List<string> st = new List<string>();
    ob = st.Cast<object>();
    

    And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:

    List<string> st = new List<string>();
    List<object> ob = st.Cast<object>().ToList();
    

    I like more the second way. I hope this helps.

    0 讨论(0)
  • 2020-11-22 04:44

    You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.

    To do this pre-NET 3.5:

    List<string> sl = new List<string>();
    // Add strings to sl
    
    List<object> ol = new List<object>();
    
    foreach(string s in sl)
    {
        ol.Add((object)s);  // The cast is performed implicitly even if omitted
    }
    

    Using Linq:

    var sl = new List<string>();
    // Add strings to sl
    
    var ol = new List<object>(sl.Cast<object>());
    
    // OR
    var ol = sl.Cast<object>().ToList();
    
    // OR (note that the cast to object here is required)
    var ol = sl.Select(s => (object)s).ToList();
    
    0 讨论(0)
提交回复
热议问题