Click here to Skip to main content
15,878,809 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Collection<BaseType> CollectionBaseType;
Collection<DerivedType1> CollectionDerivedType1;
Collection<DerivedType2> CollectionDerivedType2;


When I declare a collection of the type Collection<basetype> and try to assign to it an instance of Collection<derivedtype1> or Collection<derivedtype2>, I get a compiler error. This means that I cannot benefit of inheritance when dealing with collections like this.

Is there a way to define a variable that can hold Collection<basetype>, Collection<derivedtype1>, or Collection<derivedtype2>?

What I have tried:

Collection<BaseType> CollectionBaseType;
Collection<DerivedType1> CollectionDerivedType1;
Collection<DerivedType2> CollectionDerivedType2;
Posted
Updated 26-May-17 20:15pm

You could use object, but I guess, it's not what you want to achieve.

It's not possible to go from a base type to a derived due the circumstance the compiler couldn't know what type you expect. There are (at least) two possible scenarios for
C#
CollectionDerivedType1 = CollectionBaseType;

All the objects, which are not DerivedType1

1. get skipped
2. are null

If you want to filter you could use LINQ, if it this you want to achieve.

Hope this will help.
 
Share this answer
 
The problem is that the two lists aren't covariant:
Quote:
In object-oriented programming, a covariant return type of a method is one that can be replaced by a "narrower" type when the method is overridden in a subclass. A notable language in which this is a fairly common paradigm is C++. C# does not support return type covariance.
(Covariant return type - Wikipedia[^])

What that basically means is that if you construct collections:
C#
class Animal {...}
class Ape : Animal {...}
class Feline : Animal {...}

List<Ape> apes = new List<Ape>();
List<Feline> cats = new List<Feline>();
List<Animal> animals = new List<Animal>();
Then because an Ape is an Animal, you can add a new species to either collection:
C#
Ape newSpecies = new Ape("Pans Sapiens");
apes.Add(newSpecies);
animals.Add(newSpecies);
But if you try to add it to the Felines:
C#
cats.Add(newSpecies);
You will get a compilation error:
Argument 1: cannot convert from 'GeneralTesting.frmMain.Ape' to 'GeneralTesting.frmMain.Feline'
And that is what you would expect.
But ... if you could do what you want, you could do this:
C#
Ape newSpecies = new Ape("Pans Sapiens");
animals = cats;
animals.Add(newSpecies);
And you would have an Ape in your Feline collection - which means your application will crash later on when you try to use it.

You can add all the items:
C#
animals = new List<Animal>();
List<Ape> apes = new List<Ape>();
List<Feline> cats = new List<Feline>();
...
animals.AddRange(apes);
animals.AddRange(cats);

Or even explicitly:
C#
animals = new List<Animal>();
List<Ape> apes = new List<Ape>();
List<Feline> cats = new List<Feline>();
...
animals.AddRange(apes.ConvertAll(x => (Animal)x));
animals.AddRange(cats.ConvertAll(x => (Animal)x));

But you can't assign items which aren't covariant.
 
Share this answer
 
Comments
StM0n 28-May-17 2:15am    
Ah... covariant was the term I was looking for. Damn, too old to remember :)
OriginalGriff 28-May-17 2:21am    
There are far too many specialist terms to rmember 'em all! :laugh:

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900