不能有两个具有相同签名但不同通用约束的方法

时间:2016-12-21 09:18:42

标签: c# generics

我有这个方法:

library(data.table)

df = data.table(
  In=as.Date('2008-12-18') + cumsum(c(0,4,7,7,8,1,5)),
  Out=as.Date('2008-12-19') + cumsum(c(0,4,10,3,8,1,5)),
  tag=1)

toMerge = df[, .(In=Out+1, Out=shift(In-1, type='lead'), tag=0)][In <= Out]

> merge(df, toMerge, all=T)
#            In        Out tag
# 1: 2008-12-18 2008-12-19   1
# 2: 2008-12-20 2008-12-21   0
# 3: 2008-12-22 2008-12-23   1
# 4: 2008-12-24 2008-12-28   0
# 5: 2008-12-29 2009-01-02   1
# 6: 2009-01-03 2009-01-04   0
# ...

现在我希望此方法也出现在public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, TResult> func) where TResult : AnotherType 中。所以我写了这个,显然没有编译:

IEnumerable<AnotherType>

我收到编译错误:

  

已声明相同签名的成员

我读了Member with the same signature already defined with different type constraints,它使用另一种返回类型来处理成员。但是在我的例子中,我没有区分方法return-type,而是在它的param-list上,首先是public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, TResult> func) where TResult : IEnumerable<AnotherType> ,第二个是Func<MyType, TResult>。但是编译器无法处理这个问题。

还有另一种方法,而不是第二个例子的另一个方法名称?

1 个答案:

答案 0 :(得分:5)

确实,两个方法重载不允许仅仅由通用约束区分开来。

在你的情况下,我想知道你是否需要TResult(正如Alfie Goodacre所评论的那样)因为IEnumerable<out T>中的T是协变的,Func<in T1, out TResult>中的协变是TResult {1}}。

所以试试:

public IEnumerable<MyType> DoSomething(Func<MyType, AnotherType> func) 

public IEnumerable<MyType> DoSomething(Func<MyType, IEnumerable<AnotherType>> func) 

由于上面提到的协方差,在调用上述重载时使用比AnotherType派生的类更好。

另一种选择:

public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, TResult> func) 
  where TResult : AnotherType

public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, IEnumerable<TResult>> func) 
  where TResult : AnotherType

在这种替代方法中,签名不同,并且两个过载中的约束相同。即使AnotherTypeinterfaceTResult是实现接口的struct(值类型),这也可以起作用,这是协方差(out Tout TResult)不起作用。