Converting a List of Base type to a List of Inherited Type

后端 未结 4 1329
独厮守ぢ
独厮守ぢ 2020-12-09 09:36

I would be certain that this question addresses something that would have been brought up in a previous question, but I was unable to find it.

There is a method in a

相关标签:
4条回答
  • 2020-12-09 09:57

    You cannot do that. To understand why it is not allowed, imagine what would happen if Add was called on a List<Derived> after it had been cast to a List<Base>.

    Also, the answers implying that C# 4.0 will be different are wrong. List will never be modified to allow you to do this. Only IEnumerable will - because it does not allow items to be added to the collection.

    Update: The reason it works in the solution you've gone for is because you're no longer passing the same list. You're creating a whole new list which is a copy of the original. This is why I asked about modifying the list; if MethodC makes changes to the number of items on the list, those changes would be made to a copy, not the original list.

    I think the ideal solution for you is as follows:

    public abstract class A
    {
        public void MethodC<TItem>(List<TItem> list) where TItem : A
        {
            foreach (var item in list)
                item.CanBeCalled();
        }
    
        public abstract void CanBeCalled();
    }
    
    public class B : A
    {
        public override void CanBeCalled()
        {
            Console.WriteLine("Calling into B");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            List<B> listOfB = new List<B>();
    
            A a = new B();
    
            a.MethodC(listOfB);
        }
    }
    

    Notice how, with this solution, you can pass a List<B> directly to MethodC without needing to do that weird conversion on it first. So no unnecessary copying.

    The reason this works is because we've told MethodC to accept a list of anything that is derived from A, instead of insisting that it must be a list of A.

    0 讨论(0)
  • 2020-12-09 10:08

    Here is an answer that will exclude any objects in your list of the wrong type. This is a much safer way in my opinion:

    List<A> ListOfA  = ListOfB.OfType<A>().ToList();
    

    The OfType method will exclude items of the wrong derived class where as the Cast will throw an error.

    0 讨论(0)
  • 2020-12-09 10:15

    If you have linq available you can do

    var ListOfA = ListOfB.Cast<A>().ToList();
    
    0 讨论(0)
  • 2020-12-09 10:18

    You are addressing the lack of covariance in the current C# version. Here is one way of doing it:

    listOfB.Cast<A>();
    
    0 讨论(0)
提交回复
热议问题