0

I have the following problem. I have an interface IUserGroup and an implementation for Entity Framework UserGroupEF. The code is (sorry, variables are mostly in Polish):

public partial class UzytkownikGrupaEF : IUzytkownikGrupa
{
    //something
}

public partial class GrupaEF 
{
 private ICollection<UzytkownikGrupaEF> _Uzytkownicy;

  public virtual ICollection<UzytkownikGrupaEF> UzytkownicyEF
    {
        get { return _Uzytkownicy; }
    }
    /*
    ...
    */
     [NotMapped]
    public ICollection<IUzytkownikGrupa> Uzytkownicy //so in application i dont have to use EF types - just interfaces
    {
        get { return (ICollection<IUzytkownikGrupa>)this.UzytkownicyEF; } //Here is problem - i cant cast Collection<UzytkownikGrupaEF> to ICollection<IUzytkownikGrupa>         
    }
}

So as you can see I would like to be able to do a nice and clean cast from Collection<UserGroupEF> to ICollection<IUserGroup> without doing weird loops and copying data.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
Bartek Wójcik
  • 473
  • 3
  • 15
  • 1
    A bowl of fruit is not a bowl of apples; it might contain a banana. A bowl of apples is not a bowl of fruit, because it is legal to put a banana in a bowl of fruit, but not legal to put one in an bowl of apples. Since no matter which way you look at it, there is an incompatibility between the types, they are not compatible types. What you want is not legal in C# because it is not safe. – Eric Lippert Apr 17 '15 at 15:48
  • What if another class implemented `IUzytkownikGrupa`? Then you could add whatever those things are to the collection; but the collection is really a collection of `UzytkownikGrupaEF`s, so whatever those other things are cannot really be in the collection. – Dave Cousineau Apr 17 '15 at 18:15

1 Answers1

2

First of all here is Eric Lippert's explanation about co-/contr-variance in C# Why can I not assign a List of concrete types to a List of that concrete's interface? So to make it working you need to change property type to IEnumerable as IEnumerable is covariant (in C# 4) and ICollection is not.

[NotMapped]
public IEnumerable<IUzytkownikGrupa> Uzytkownicy    {
    get { return this.UzytkownicyEF; }
}

Second, you can Enumerable.Cast method to convert your collection.

Community
  • 1
  • 1
Artur Shamsutdinov
  • 3,127
  • 3
  • 21
  • 39
  • But I need be able to add items to collection, which IEnumerable is not supporting. And when i'm doing this: `get { return this.UzytkownicyEF.Cast().ToList(); }` i'm losing reference to `this.UzytkownicyEF` and new list is beeing returned so adding items to collection is useless. – Bartek Wójcik Apr 16 '15 at 14:34
  • If you need to add items, the simplest solution will be to implement Add method accepting IUzytkownikGrupa in your class and keep property as IEnumerable. – Artur Shamsutdinov Apr 16 '15 at 20:53
  • 1
    The problem is that adding and changing items is not safe and as Eric Lippert said in C# covariance is always safe. That's why IEnumerable is covariant and ICollection/IList is not. – Artur Shamsutdinov Apr 16 '15 at 20:55
  • 1
    There are two ways to add a banana to a bowl of apples: 1) Don't use a bowl of apples in the first place. Start with a bowl of fruit. 2) Create a new bowl every time you add something (if done carefully, this isn't quite as inefficient as it sounds). An interesting example of #2 is Eric Lippert's [Immutable Stack](http://blogs.msdn.com/b/ericlippert/archive/2007/12/06/immutability-in-c-part-three-a-covariant-immutable-stack.aspx) – Brian Apr 20 '15 at 12:22