Reputation: 3930
I have classes that inherit from an abstract base class, and I want to pass a List
of any of those classes into a method that that has a List
of the base class as a parameter. How can I make that happen?
Here is want I've tried -
public abstract class MyBaseClass {}
public class MyClass1 : MyBaseClass {}
//Inside another class
public void MyMethod(List<MyBaseClass> listOfBaseClass){}
//Inside another class
List<MyClass1> myClass1List = new List<MyClass1>();
MyMethod(myClass1List); //ERROR HERE, This method call does not compile
Is there anyway to accomplish what I am trying to do?
Upvotes: 3
Views: 769
Reputation: 2276
You can also change the signature to be generic, and then constrain the generic type to be a subclass of your base class:
public void MyMethod<T>(List<T> listOfBaseClass) where T : MyBaseClass {}
Now you can pass a list of subclasses.
Upvotes: 0
Reputation: 8498
Declare your method with a parameter of type IReadOnlyList<T>
.
You cannot receive List<T>
or IList<T>
because they are not read-only. If you could pass a List<MyClass1>
argument into a method as a IList<MyBaseClass>
parameter, the method could attempt to add a MyClass2
object into the list (assuming MyClass2
is another inheritor of MyBaseClass
). It would be OK from the method's perspective, but it would cause runtime failure - so the C# language prevents it right off.
Your problem will be solved if you would use a read-only list. For example, a parameter of type IReadOnlyList<MyBaseClass>
would accept argument of type List<MyClass1>
- because List<T>
implements IReadOnlyList<T>
, and IReadOnlyList<T>
declares T
as out
.
In this way you don't have to resort to IEnumerable<T>
, and won't lose count and random access by index.
Upvotes: 1
Reputation: 107317
If you want to pass collections of derived types of MyBaseClass
, you'll need to change the signature
public void MyMethod(List<MyBaseClass> listOfBaseClass){}
To a type which supports covariance, such as IEnumerable
or IReadOnlyCollection
, e.g.:
public void MyMethod(IEnumerable<MyBaseClass> listOfBaseClass){}
This is because List
is invariant, whereas IEnumerable
is covariant. The reason why the compiler is strict is because List
allows for change to the collection, e.g. if MyMethod
would be allowed to do this:
public void MyMethod(List<MyBaseClass> listOfBaseClass)
{
listOfBaseClass.Add(new AnotherClass());
}
Where AnotherClass
was another subclass of MyBaseClass
, it would break
the caller's collection which was supposed to be of List<MyClass1>()
;.
More about this here
Upvotes: 6