Интерфейс со списком интерфейсов - PullRequest
3 голосов
/ 30 апреля 2009

Может быть, я тупой, но ...

У меня есть:

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

    // stuff
}

public interface IRequestDetail
{
    // stuff
}

У меня тогда есть:

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

    // stuff
}

public class MyRequestDetail : IRequestDetail
{
    // stuff
}

Это не работает.

C # разозлился на меня, потому что MyRequest не реализует интерфейс из-за отсутствия IList из IRequestDetail.

Теперь, если я изменил его так, чтобы Details был IList для IRequestDetail, мне пришлось бы привести его к MyRequestDetail везде в коде, где я использую неинтерфейсный член (у меня есть несколько запросов, которые разделяют общие вещи, но затем специализируются). 1013 *

Я вроде понимаю, почему это неправильно, но не полностью!

Ответы [ 3 ]

12 голосов
/ 30 апреля 2009

Я думаю, исходя из вопроса, что проблема заключается в том, что вы хотите рассматривать Details как общий список и принудительно применять IRequestDetail. Вы также хотите, чтобы он был более конкретно напечатан для реализующих классов. В этом случае вам нужно сделать IRequest универсальным.

Попробуйте это:

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
}

Это должно сработать для вас.

РЕДАКТИРОВАТЬ 2017-03-17

В ответ на комментарий @ Robert см. Расширенный код ниже:

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);
    }
}
2 голосов
/ 30 апреля 2009

Exact. У Майкла есть решение. проблема немного сложнее.

это означает, что нет явного преобразования из

IList<MyRequestDetail>

до

IList<IRequestDetail>

потому что это может означать, что вы можете добавить другие объекты, основанные на разных классах (например, MyRequestDetail2), которые не являются «MyRequestDetail», ко второму объекту. и это было бы незаконно для первого.

0 голосов
/ 30 апреля 2009

Это связано с ковариацией и контравариантностью в C #. Блог Эрика Липперта .

содержит очень подробное, очень четкое объяснение проблем.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...