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
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
.
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.
If you have linq available you can do
var ListOfA = ListOfB.Cast<A>().ToList();
You are addressing the lack of covariance in the current C# version. Here is one way of doing it:
listOfB.Cast<A>();