Question

I'm trying to wrap my head around interfaces. I keep stumbling on implimenting something like this:

public interface IFoo
{
    ICollection<IBar> Bars { get; set; }
    //some other properties
}
public interface IBar
{
    //some properties
}
//assume Bar is implemented and extends IBar. Some instaces of Bar are created
Bar[] MyBars = {bar1, bar2};
Foo MyFoo = new Foo();
MyFoo.Bars=MyBars.ToList(); //This causes an error saying Collection<Bar> cannot be
//assigned to ICollection<IBar>.

I'm completely at a loss on how to do this properly. What is the proper way to populate a collection of interfaces?

edit: The way I've implemented Foo is probably part of the problem.

public class Foo : IFoo
{
    public ICollection<IBar> Bars { get; set; }
}
Was it helpful?

Solution

The problem is the Foo class which should be:

public class Foo : IFoo
{
    public ICollection<Bar> Bars { get; set; }
}

Or if you want to use ICollection<IBar>:

IBar[] MyBars = { bar1, bar2 };
Foo MyFoo = new Foo( );
MyFoo.Bars = MyBars.ToList( );

Or the more elegant solution:

Bar[] MyBars = { bar1, bar2 };
Foo MyFoo = new Foo( );
MyFoo.Bars = MyBars.ToList<IBar>( ); //Cast from Bar to IBar

Infact the problem happened because you could't convert ICollection<Bar> to ICollection<IBar>.

OTHER TIPS

How you have implemented the Bars property matters here. You cannot assign a concrete type to an interface type. When you try to do the ToList conversion, you are converting it to concrete list type and trying to assign it to ICollection interface type, hence it is generating error.

The following should work fine.

public class Foo:IFoo
{
    public ICollection<IBar> Bars { get; set; }
}

Bar bar1 = new Bar();
Bar bar2 = new Bar();
Bar[] MyBars = { bar1, bar2 };
Foo MyFoo = new Foo();
MyFoo.Bars = MyBars;

For your way, you can do it like so:

ICollection<Bar> MyBars = new Bar[] {bar1, bar2};
MyFoo.Bars = MyBars;

You can also do it this way, which, programmatically might be better for you:

List<Bar> lstBar = new List<Bar>();
lstBar.Add(bar1);
lstBar.Add(bar2);
MyFoo.Bars = lstBar;

The whole source:

public interface IFoo
{
    ICollection<IBar> Bars { get; set; }
}
public interface IBar
{

}
public class Foo : IFoo
{
    public ICollection<IBar> Bars { get; set; }
}
public class Bar : IBar
{
}

class Program
{
    static void Main(string[] args)
    {
        IFoo myFoo = new Foo();
        List<IBar> lstBar = new List<IBar>();
        lstBar.Add(new Bar());
        myFoo.Bars = lstBar;
    }
}

It won't work this way. See, ICollection<T> is not covariant on T, therefore an ICollection<Bar> is not an ICollection<IBar> even though Bar is an IBar.

Why is it so? Imagine that there is some Quux implementing IBar. If you could assign ICollection<Bar> to ICollection<IBar>, someone could insert a Quux into the collection using ICollection<IBar>.Add, because Quux is an IBar, too! But the collection is a collection of Bars, so the type safety would be broken.

You should try

IBar[] MyBars = {bar1, bar2};

This way your MyBars allows insertion of other IBars, not only Bars.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top