Farnam
Farnam

Reputation: 177

C# implement interface with properties that are interface.

I am using EF code first to generate my db and I do need concrete property for ICollection of EF entity models. I am writing a data access layer ( Using generic classes) however hit the following road block with using interfaces in my generic class as shown below.

public interface ITestClassProp
{
    int Value { get; set; }
}

public class TestClassProp : ITestClassProp
{
    public int Value { get; set; }
}


public interface ITestClass
{
    ICollection<ITestClassProp> TestProp { get; set; }
}

public class TestClass : ITestClass
{
    // works
    //public ICollection<ITestClassProp> TestProp { get; set; }
    // does not work
    public ICollection<TestClassProp> TestProp { get; set; }
}

Am I totally mis using the interfaces? why cant I use TestClassProp instead of ITestClassProp?

Thanks

Upvotes: 1

Views: 112

Answers (3)

David L
David L

Reputation: 33863

As you've currently written your code, you are not satisfying the requirement you've imposed via your ITestClass interface, which is to have a property of ICollection<ITestProp>.

One way around this is to actually make ITestClass generic, but provide a generic constraint of ITestClassProp

public interface ITestClassProp
{
    int Value { get; set; }
}

public class TestClassProp : ITestClassProp
{
    public int Value { get; set; }
}


public interface ITestClass<T> where T : ITestClassProp
{
    ICollection<T> TestProp { get; set; }
}

public class TestClass : ITestClass<TestClassProp>
{
    public ICollection<TestClassProp> TestProp { get; set; }
}

This allows you to provide any concrete type that implements ITestProp to your ICollection.

Upvotes: 0

plinth
plinth

Reputation: 49199

Simply, the interface declares a property of type ICollection, but you implement it as ICollection, which has a totally different signature.

You might want to read up on covariance and contravariance also.

Upvotes: 0

mason
mason

Reputation: 32699

When you implement an interface, you have to implement the methods/properties of that interface with the same signature. Since the interface declares ICollection<ITestClassProp> TestProp { get; set; } then your TestClass must also declare ICollection<TestClassProp> TestProp { get; set; }.

The reason this is necessary is that other classes that know about the interface but not the concrete class are expecting the property to be ICollection<ITestClassProp> and not ICollection<TestClassProp>.

Upvotes: 3

Related Questions