How do I cast a List effectively?

前端 未结 8 1386
暖寄归人
暖寄归人 2020-12-08 15:09

I have a

List 

but I need a

List  

Is there a way to cast this in c

相关标签:
8条回答
  • 2020-12-08 15:35

    Just in case: I've little C# experience, but if this generic construction means the same thing it does in Java, then you must create a whole new List parametrized by the supertype. In other words, if every instance of Bangle is also an instance of Akthud, it does not follow that every List<Bangle> is also a List<Akthud>.

    The reason for this is that you can have two references to this List<Bangle>. If the second reference casts and then refers to it as a List<Akthud>, then it is permitted to add an Akthud to it - but now the first reference has a List<Bangle> whose members are not all Bangles. Violation!

    That being said, David B's answer should indeed do what you want, correctly, AFAICT. (It looks like a copy operation.)

    [And if I'm misunderstanding the semantics of C# generics, I hope someone corrects me in a comment!]

    0 讨论(0)
  • 2020-12-08 15:36

    ConvertAll seems like a better solution, since it doesn't depend on Linq library and is shorter and more intuitive.

    But both of them are rather workarounds, than solutions. Both of them create a new collection with the same data. There should be a support for generic covariance in .net, i.e. upcasting in the generic collections, which would allow you to do that naturally. For example:

    List<IDataField> ls = (List<IDataField>)List<InputField>
    

    From my search so far, my conclusion, is that .Net as of 3.5 doesn't support this feature. Hence we have to end up with workarounds.

    These are the discussions on the topic:

    • C# generic Covariance
    • Covariant Generic List
    • Are Generics Covariant, Contra-Variant, or Invariant?
    0 讨论(0)
  • 2020-12-08 15:41

    I don't know that a direct cast would have the desired effect. The rare few times I've done this, it's usually something like:

    List<InputField> list = .....
    List<IDataField> list2 = new (List<IDataField>((IDataField[])list.ToArray()));
    
    0 讨论(0)
  • 2020-12-08 15:43

    You could also use List.ConvertAll.

    Documentation: http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

    Example:

    List<IDataField> newList = oldList.ConvertAll(i => i as IDataField);
    
    0 讨论(0)
  • 2020-12-08 15:46

    Both .OfType<T> and .Cast<T> will return a list of T, but the meaning of the two methods is different.

    list.OfType() filters the original list and returns all items which are of type T, and skips the ones that are not of that type.

    list.Cast() casts all items in the original list to type T, and throws an exception for items which cannot be cast to that type.

    In your case both would give the same result, but using .Cast() would communicate your intent a lot more clearly, so I would recommend using that.

    List<InputField> list = (from i .... select i).Cast<IDataField>().ToList();
    
    0 讨论(0)
  • 2020-12-08 15:47
    List<InputField> raw = (from i .... select i).ToList();
    List<IDataField> result = raw.OfType<IDataField>().ToList();
    
    0 讨论(0)
提交回复
热议问题