Является ли C # 4.0 ковариантным кортежем - PullRequest
11 голосов
/ 20 мая 2010

(я бы проверил это для себя, но у меня нет VS2010 (пока))

Скажем, у меня есть 2 базовых интерфейса:

IBaseModelInterface
IBaseViewInterface

И 2 интерфейса, реализующих те:

ISubModelInterface : IBaseModelInterface
ISubViewInterface : IBaseViewInterface

Если я определю Tuple<IBaseModelInterface, IBaseViewInterface>, я бы хотел установить его на основе результата фабрики, которая возвращает Tuple<ISubModelInterface, ISubViewInterface>.

В C # 3 я не могу этого сделать, хотя подчиненные интерфейсы реализуют базовые интерфейсы. И я уверен, что C # 4 позволяет мне делать это, если я использовал IEnumerable<IBaseModelInterface>, потому что теперь он определен с ключевым словом in, чтобы разрешить ковариацию. Так позволяет ли Tuple мне это сделать?

Из того, что (мало) я понимаю, ковариация разрешена только для интерфейсов, значит ли это, что должен быть интерфейс ITuple<T1, T2>? Это существует?

Ответы [ 2 ]

12 голосов
/ 20 мая 2010

Tuple - это класс (ну, семейство классов) - он инвариантен по определению. Как вы упоминаете позже, только интерфейсы и типы делегатов поддерживают общую дисперсию в .NET 4.

Нет интерфейса ITuple, о котором я знаю. Может быть один, который будет ковариантным, так как кортежи неизменны, поэтому вы можете получить значения только из API.

8 голосов
/ 18 ноября 2013

Вы можете наследовать от кортежа для создания своего собственного Ковариантного кортежа. Таким образом, вам не придется переписывать свою собственную логику равенств.

public interface ICovariantTuple<out T1>
{
    T1 Item1 { get; }
}
public class CovariantTuple<T1> : Tuple<T1>, ICovariantTuple<T1>
{
    public CovariantTuple(T1 item1) : base(item1) { }
}

public interface ICovariantTuple<out T1, out T2>
{
    T1 Item1 { get; }
    T2 Item2 { get; }
}
public class CovariantTuple<T1, T2> : Tuple<T1, T2>, ICovariantTuple<T1, T2>
{
    public CovariantTuple(T1 item1, T2 item2) : base(item1, item2) { }
}

etc.... for 3, 4, 5, 6, 7, 8 items

Ошибка компиляции

Tuple<Exception> item = new Tuple<ArgumentNullException>(null);

Успех компиляции

ICovariantTuple<Exception> item = new CovariantTuple<ArgumentNullException>(null);

Нет базового кортежа после 8 предметов , но этого должно быть достаточно.

...