2

In the following C# setup a class A derived from class X and some method getting a list of List as parameter,

class X 
{...};

class A : X
{...};

List<A> listA;
List<X> listX;

void SomeMethod(ref List<X>)
{...};

is there any way to use that same method for class A (which was derived from X)? Recasting that list from A to X seems to not work.

SomeMethod(ref listX); // Works
SomeMethod(ref (List<X>)listA); // Does not work
ares_games
  • 1,019
  • 2
  • 15
  • 32
  • 4
    As a minor note, to you or to readers, make sure you really understand what ref does in C#: it's not the same as in C++, and often confuses new resharpers, and they end up using it when they don't really need to. Here's a great article providing an explanation of argument passing in C#: http://jonskeet.uk/csharp/parameters.html – Quantumplation Apr 24 '15 at 17:00
  • Yes, the ref is of course not necessary. Thanks! – ares_games Apr 24 '15 at 17:02

3 Answers3

4

Actually, it will already work because IEnumerable is covariant on its generic type parameter.

If you modify your signature like this:

void SomeMethod(ref IEnumerable<X>)
{...};

Then you can pass a List<X> or a List<A> to it and be just fine.

As a total aside, its very weird that you are passing that by ref. You usually don't pass reference types that way.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
3

Two possibilities.

One, redefine void SomeMethod(List<X> list) as void SomeMethod(IEnumerable<X> list).

Because the IEnumerable<T> is covariant, you can pass an IEnumerable<A> as to a method with an IEnumerable<X> parameter, and it will work.

Two, redefine void SomeMethod(List<X> list) as void SomeMethod<T>(List<T> list) where T : X.

Here you have a generic SomeMethod that will work with lists of any type derived from X, including X itself.

(Even better if you can is to define the method as void SomeMethod<T>(List<T> list) [without the where] or better still, as SomeMethod<T>(IEnumerable<T> list) as then you've a method applicable to even more cases than those you are currently thinking about, but I'm going to assume you need to make use of some features of X and those therefore aren't viable).

Note also that as people have said the ref is unusual here (I just took it out in the above), and it also causes further problems. To use ref you need an assignable variable (a local variable, a parameter, a settable property or an array access) of the appropriate type, as ref needs to be able to assign as well as access. Hence you can never cast when passing to a ref variable as SomeMethod(ref (List<X>)listA) attempts to do, even if listA could be cast to List<X> (which it can't anyway.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
1

Sorry for answering not to your direct question. I'd recommend you to get rid of List<A> and use List<X> both places. Create instances of A and add them to List<X>.

Now according to your direct question. It's possible as @BradleyDotNet answered. See this URL for more details and examples: https://msdn.microsoft.com/ru-ru/library/dd799517(v=vs.110).aspx

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42