2

Why this won't compile? Maybe FW5 can enable that...

    static void Main(string[] args)
    {
        List<Foo> foos = new List<Goo>(); 
    }

    public class Foo
    {

    }

    public class Goo : Foo
    {

    }

Stackover flow says my post is mostly code... But that was may question so I'm trying to pass the code text ratio validation.... Hope that is enough

Now it is saying I'm not describing the problem right.. Just read it again seems fine by me...

Amir Katz
  • 1,027
  • 1
  • 10
  • 24

2 Answers2

8

Because a list of Goo is not a list of Foo. If that worked, you could do (at compile-time):

foos.Add(new Foo());

which clearly can't work, because the list can only take Goo instances.

Variance does exist (depending on the framework version), but is limited a: to interfaces and delegates (not concrete types like lists), and b: to known-all-"in" or known-all-"out" scenarios.

For example, the following will compile on recent framework / compiler versions:

IEnumerable<Goo> goos = new List<Goo>();
IEnumerable<Foo> foos = goos;

In this scenario, it works fine because every Goo is known statically to be a Foo. Technically, this uses the out part of IEnumerable<out T> signature.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Hi Marc, thanks for your answer .. Basicly when using "IEnumerable goos = new List();" makes perfect sense to not abuse the ICollection capabilities. So (T out).. and not (T in) :) – Amir Katz Jan 27 '14 at 12:44
5

The reason you're not allowed to do that is that it would allow code like this:

public class Mammal {}

public class Cat: Mammal {}

public class Dog: Mammal {}

...

List<Cat> cats = new List<Cat>();

List<Mammal> mammals = cats; // Imagine this compiles.

mammals.Add(new Dog()); // We just added a dog to the list of cats!
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276