0

I have two classes.... Parcel and FundParcel...and I'm trying to convert an IEnumerable of the subtype to an IList of the supertype....

public class FundParcel : Parcel
{
  /* properties defined here */
}

public class Parcel
{
  /* properties defined here */
}

These are used in another class in a method as follows:

private IList<Parcel> ExtractParcels(IEnumerable<FundParcel> fundParcels)
{
    var parcels = new List<Parcel>();

    foreach (var fp in fundParcels)
        parcels.Add(fp);

    return parcels;
}

What I don't understand is why the foreach statement can't be reduced to:

parcels.AddRange(fundParcels);

I basically get an error that says "Argument type 'System.Colection.Generic.IEnumerable<FundParcel>' is not assignable to parameter type 'System.Collections.Generic.IEnumerable<Parcel>'"

But if that's the case then I don't understand why parcels.Add works...

I feel as though the entire method ought to be replaceable with the line:

return (List<Parcel>)fundParcels;

...or maybe the method can be scrapped alltogether since subtypes should be substitutable for their supertype..

Can anyone explain what the deal is with AddRange in this case and why the for loop may be necessary in this case?

Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
mezoid
  • 28,090
  • 37
  • 107
  • 148
  • Possible duplicate of [Why does C#/CLR not support method override co/contra-variance?](http://stackoverflow.com/questions/837134/why-does-c-clr-not-support-method-override-co-contra-variance) – TheLethalCoder Jun 13 '16 at 13:30

2 Answers2

4

This SO will probably answer your question and also will point you to references about upcoming C# 4.0 which will support Co-/Contra-variance to a certain degree.

Community
  • 1
  • 1
Michael Bray
  • 14,998
  • 7
  • 42
  • 68
  • 1
    "Solved" is too strong a word - the general issue is still there, but C# 4 will fix it for *some* cases, including IEnumerable. – Jon Skeet Jul 02 '09 at 06:03
1

Consider this code:

void AddParcelToParcelList(List<Parcel> parcels) {
  parcels.add(new Parcel());
}

List<FundParcel> fundParcels = new List<FundParcels>();
AddParcelToParcelList(fundParcels);

If containers of inherited classes also inherited from containers of the base classes, the above code would be valid, and generate a case where a list of the inherited class contains an object of the base class.

Tal Pressman
  • 7,199
  • 2
  • 30
  • 33