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

Является ли С# 4.0 кортежем ковариантным

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

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

IBaseModelInterface
IBaseViewInterface

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

ISubModelInterface : IBaseModelInterface
ISubViewInterface : IBaseViewInterface

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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);

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