Является ли С# 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>
? Это существует?
Ответы
Ответ 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 элементов, но этого должно быть достаточно.