2010-05-20 44 views
11

(我检查了这一点为自己,但我没有VS2010(还))是C#4.0元组协

说我有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>接口?这是否存在?

+3

请注意,“in”关键字允许*反差*,而不是*协方差*。 IEnumerable 被标记为* out *,因为* T来自IEnumerable *。 – 2010-05-20 14:16:15

回答

12

Tuple是一个类(当然,类家庭) - 这是通过定义不变。至于你提到的以后,只有接口和委托类型支持.NET 4

有没有ITuple接口,我所知道的一般变化。可能有一个是协变的,因为元组是不可变的,所以你只能得到API的值。

+0

我想我可以在TBaseView中定义我自己的IMyTuple ,这将是整洁的 – RichK 2010-05-20 11:15:07

+1

@RichK - 如果你打算编写自己的元组类,你应该仔细检查由BCL元组提供的比较和相等语义。我假设你想要保持与内置类中提供的行为相同的行为 - 并且其中一些行为并不明显。 – LBushkin 2010-05-20 13:28:12

+2

@乔恩飞碟双向,还有一个非泛型'ITuple'接口,但它的内部 – smartcaveman 2012-11-09 15:23:12

8

您可以从元组继承创建自己的协变元组。这样你就不必重写自己的平等逻辑。

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,但它应该是足够了。

+0

我喜欢你的解决方案,接口和伴侣课!但空厂的目的是什么?我认为最后两个例子显示了什么有效而不是。 – MEMark 2014-02-26 18:40:28