Подтвердить что ты не робот

Интегрированные интерфейсы

Я часто хотел создать список объектов, где каждый объект должен реализовывать ряд интерфейсов. Например, я хотел бы сделать что-то похожее на следующее:

List<T> where T : IConvertible, IComparable _myList;

Еще один вариант, который я рассматривал, - создать третий интерфейс, который реализует эти два, чтобы любой объект, реализующий эти два интерфейса, по своей сути реализует мои.

public interface IConvertibleAndComparable
    : IConvertible, IComparable { }

List<IConvertibleAndComparable> _myList;

С этим я бы мог добавить любой объект, который реализует как IConvertible, так и IComparable, включая double и int, а также мои собственные объекты. Явно реализовать IConvertibleAndComparable не требуется, поскольку он не добавляет никаких новых функциональных возможностей за пределы интерфейсов в наследованиях.

Я понимаю, что первый фрагмент является незаконным, а второй, хотя и законным, не делает то, что я хочу. Можно ли достичь того, что я пытаюсь сделать? Если нет, будет ли кто-нибудь из них быть кандидатом на будущую функцию С#?

(Примечание. Это было бы законным приложением для пустых интерфейсов.)

Edit

В более общем смысле я хотел бы выполнить одно из следующих действий:

private MyGenericClass<T> where T : IA, IB, ... _myClass;

где я могу объявить все ограничения на T, которые мне нужны, или

public interface IMyCombinedInterface : IA, IB, ... {}
private MyGenericClass<IMyCombinedInterface> _myClass;

где любой тип, реализующий IA, IB и ... по своей сути (или неявно) реализует IMyCombinedInterface (только если IMyCombinedInterface явно не объявляет новую функциональность).

4b9b3361

Ответ 1

В качестве обходного пути вы можете сделать своего рода суперпозиционную оболочку и сохранить ее в списке. Посмотрите здесь для этой идеи.

В ваш пример вы можете сделать:

public class Junction
{
    public IConvertible Convertible { get; private set; }
    public IComparable Comparable { get; private set; }
    private Junction() { }
    public static Junction Create<T>(T value) where T : IConvertible, IComparable
    {
        return new Junction
        {
            Convertible = value,
            Comparable = value
        };
    }
}

И затем добавьте Junction в свой список:

var l = new List<Junction>();
l.Add(Junction.Create(1));

Ответ 2

Во время работы над другим проектом у меня возникла идея еще одного обходного пути. Хотя это может не сработать для примера, который я опубликовал, он может работать для первоначального намерения вопроса, а именно для создания комбинационного интерфейса для IEnumerable<T> и INotifyCollectionChanged (как отметил @DanielHilgarth). Обходной путь выглядит следующим образом:

Создайте пустой интерфейс, который реализует комбинацию необходимых вам интерфейсов.

public interface INotifyingEnumerable<T> :
    IEnumerable<T>,
    INotifyCollectionChanged
{
}

Создайте новый класс, который наследует от класса, реализующего оба из них, и реализует новый интерфейс.

public class MyObservableCollection<T> :
    ObservableCollection<T>,
    INotifyingEnumerable<T>
{
}

Теперь вы можете использовать интерфейс INotifyingEnumerable<T> как тип свойства, который использует вашу реализацию.

Причина, по которой это не совсем касается первоначальных требований, однако, заключается в том, что она не позволяет напрямую назначать ObservableCollection<T>. Функция, запрошенная в исходном сообщении, позволит это.