【问题标题】:Is C# 4.0 Tuple covariantC# 4.0 元组是协变的吗
【发布时间】:2010-05-20 10:28:20
【问题描述】:

(我会自己检查一下,但我还没有 VS2010)

假设我有 2 个基本接口:

IBaseModelInterface
IBaseViewInterface

以及实现这些的 2 个接口:

ISubModelInterface : IBaseModelInterface
ISubViewInterface : IBaseViewInterface

如果我定义一个Tuple<IBaseModelInterface, IBaseViewInterface>,我想根据返回Tuple<ISubModelInterface, ISubViewInterface> 的工厂的结果来设置它。

在 C# 3 中,即使子接口实现了基本接口,我也无法做到这一点。而且我很确定如果我使用 IEnumerable<IBaseModelInterface>,C# 4 允许我这样做,因为它现在使用 in 关键字定义以允许协方差。那么Tuple 允许我这样做吗?

据我了解(很少),协方差只允许在接口上使用,这是否意味着需要有一个ITuple<T1, T2> 接口?这存在吗?

【问题讨论】:

  • 请注意,“in”关键字允许逆变,而不是协方差。 IEnumerable 被标记为 out,因为 T 来自 IEnumerable

标签: c# covariance tuples


【解决方案1】:

Tuple 是一个类(嗯,是一个类族)——根据定义它是不变的。正如您稍后提到的,只有接口和委托类型支持 .NET 4 中的泛型变化。

我知道没有ITuple 接口。可能有一个是协变的,因为元组是不可变的,所以你只能从 API 中获取值。

【讨论】:

  • 我想我可以定义我自己的 IMyTuple 那会很整洁
  • @RichK - 如果您确实打算编写自己的元组类,您应该仔细检查 BCL 元组提供的比较和相等语义。我假设您希望保留与内置类中提供的相同行为 - 其中一些行为是不明显的。
  • @Jon Skeet,有一个非通用的ITuple 接口,但它是内部的
  • @smartcaveman:是的,有,TRest如果是ITuple,就会被检查。
【解决方案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);

There is no base Tuple after 8 items,不过应该够用了。

【讨论】:

  • 我喜欢你的界面和配套类的解决方案!但是空工厂的目的是什么?我认为最后两个示例确切地说明了哪些有效,哪些无效。
猜你喜欢
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多