Question

Maybe I'm dumb but ...

I have:

public interface IRequest
{
    IList<IRequestDetail> Details { get; set; }

    // stuff
}

public interface IRequestDetail
{
    // stuff
}

I then have:

public class MyRequest : IRequest
{
    IList<MyRequestDetail> Details {get; set; }

    // stuff
}

public class MyRequestDetail : IRequestDetail
{
    // stuff
}

It doesn't work.

C# gets pissed at me because MyRequest does not implement the interface due to not having an IList of IRequestDetail.

Now if I change it so the Details is IList of IRequestDetail I then have to cast it to MyRequestDetail everywhere in the code I use a non-interface member (I have several requests that share common stuff, but then specialize).

I kind of understand why its wrong, but not fully!

Was it helpful?

Solution

I think, based on the question that the problem is that you want to treat Details as a generic list and enforce that it implements IRequestDetail. You also want it to be more specifically typed for the implementing classes. In this case, you need to make IRequest generic.

Try this:

public interface IRequest<T> where T : IRequestDetail
{
    IList<T> Details { get; set; }

    // stuff
}

public class MyRequest : IRequest<MyRequestDetail>
{
    public IList<MyRequestDetail> Details {get; set; }

    // stuff
}

This should work for you.

EDIT 2017-03-17

In reply to @Robert's comment, see the expanded code below:

public interface IRequestDetail
{

}

public class MyRequestDetail : IRequestDetail
{

}

public interface IRequest<T> where T : IRequestDetail
{
    IList<T> Details { get; set; }

    // stuff
}

public class MyRequest<T> : IRequest<T>
    where T : IRequestDetail
{
    public IList<T> Details { get; set; }

    // stuff
}

public class Consumer
{
    public void MyFunction<T>(IRequest<T> request)
        where T : IRequestDetail
    {

    }

    public void Foo()
    {
        var test = new MyRequest<MyRequestDetail>();
        MyFunction(test);
    }
}

OTHER TIPS

Exact. Michael has the solution. the problem is a little trickier.

its that there is no explicit conversion from

IList<MyRequestDetail>

to

IList<IRequestDetail>

because that would imply that you can add other objects, that are based on different classes (e.g. MyRequestDetail2), that are not "MyRequestDetail" to the second object. and that would be illegal for the first.

This is due to covariance and contravariance in C#. There is a very detailed, very clear explaination of the issues (split into many parts) on Eric Lippert's Blog.

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