Matthew
Matthew

Reputation: 11613

Generic collection collision

Here's my best attempt to recreate the situation.

public interface IFoo
{

}

public class Foo : IFoo { }

public class Bar : IFoo { }

public class CollectionOf<T> : List<IFoo>
{

}

public class Bars : CollectionOf<Bar>
{

}

public class Test
{
    public void Test()
    {
        CollectionOf<IFoo> bars = new Bars();
    }
}

Compiler complains on the instantiation. Bars is a collection of IFoos. Is this one of those covariance/contravariance issues?

Upvotes: 0

Views: 102

Answers (3)

Hans Jonus
Hans Jonus

Reputation: 385

The fix, if there is one would depend on what it is that's not working for you. I can get your example to compile in two ways, either use IEnumerable or define your CollectionOf as an interface with the out generic modifier. Whether either is a fix for you I don't know:

public interface IFoo { }

public class Foo : IFoo { }

public class Bar : IFoo { }

public interface CollectionOf<out T> : IEnumerable<IFoo> { }

public class Bars : CollectionOf<Bar> { }

public class Test
{
    public void Test()
    {
        IEnumerable<IFoo> bars1 = new Bars();
        CollectionOf<IFoo> bars2 = new Bars();
    }
}

Upvotes: 1

Ed Swangren
Ed Swangren

Reputation: 124642

Yes.

Think about it for a second; bars should legally be able to hold objects of any type that implement IFoo. However, an object of type Bars can only hold objects of type Bar.

Using your code this would be allowed, which is obviously wrong.

CollectionOf<IFoo> bars = new Bars();
bars.Add( new Foo() );  // Uh oh!

That would effectively break the type safety afforded to you via generics.

Upvotes: 4

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391336

Yes it is.

If this was allowed, you would be able to place any object into that collection, as long as it implemented the IFoo interface, but that wouldn't be safe for the collection.

Let me illustrate:

var b = new Bars();
CollectionOf<IFoo> bars = b;
bars.Add(Dummy); // implements IFoo, but does not descend from Bar

At this point, what does b contain? An object of type Dummy? That would be bad, and thus this is not allowed in the first place.

Upvotes: 2

Related Questions