Why interface is not implemented: List<string> is ICollection<string>

131 views Asked by At

Consider the C# snippet:

    interface Contract
    {
        ICollection<string> Coll { get; }
    }

    class Implementation : Contract
    {
        public List<string> Coll { get; } //this declaration is mandatory for other reason
    }

Why Implementation does not implement Contract?

List<string> implements ICollection<string>

Real case

    //Entity Framework 
    public partial class ApplicationUser : IdentityUser<Guid>
    {
      ...
      public virtual ICollection<Message> Messages { get; set; }
    }

    //Breeze.Sharp Entity 
    public partial class ApplicationUser : BaseEntity
    {
      ...
      public NavigationSet<Message> Messages
        {
            get { return GetValue<NavigationSet<Message>>(); }
        }
    }

How to find an interface that both classes implement?

1

There are 1 answers

2
MakePeaceGreatAgain On BEST ANSWER

An interface is a contract for consumers of your code. In your case that contract states: "there is a member called Coll which is of type ICollection<string>".

Implementations of your interface therefor have to follow it - that is they have to implement members exactly the same way the contract defines them - this is you need the exact same signature as of the interface.

Furthermore there´s absoluteley no way for a consumer to determine if or if not the member is of a more deerived type. In fact consumers shouldn´t care for that at all. That´s the point of an interface - to have an abstracttion about your actual implementations. So even if your implementation would work, clients have no way to use it:

Contract myContrac = new Implementation();
var list myContract.Coll; 

As the interface states, list now is of type ICollection<string>. There´s no way to call any of List<T>s members, unless you explicitely cast to List<string>, which contradicts the point of abstractions and interfaces. This way you can easily exchange the actual implementation by a newer version for example, without clients need to do anything.

EDIT: to get an interface for both your classes you can use an explicit interface-implementation:

interface BaseEntity
{
    ICollection<Message> { get; }
}
//Entity Framework 
public partial class ApplicationUser : IdentityUser<Guid>
{
    public virtual ICollection<Message> Messages { get; }
}

//Breeze.Sharp Entity 
public partial class ApplicationUser : BaseEntity
{
    public NavigationSet<Message> Messages
    {
        get { return GetValue<NavigationSet<Message>>(); }
    }
    BaseIntity.ICollection<Message> Messages { get => this.Messages; }
}