我们正在尝试构建一个采用泛型类型参数的库例程。我们遇到了一个问题,即无论我们如何约束类型,扩展方法“Union”都不会被识别为对一般类型参数有效。
这是一个简单,大大简化的例子来说明问题:
private IQueryable<int> Test(IQueryable<int> temp1, IQueryable<int> temp2)
{
return temp1.Union(temp2); // compiles fine
}
private T Test<T>(T temp1, T temp2) where T : IQueryable
{
return temp1.Union(temp2); // Error 15 'T' does not contain a definition for 'Union' and no extension method 'Union' accepting a first argument of type 'T' could be found
}
问题似乎是Union被实现为IQueryable的扩展方法,而不是作为IQueryable接口本身的一部分。似乎必须有一个相当简单的方法来完成这项工作,但我一直在通过StackOverflow和Google查看,没有任何运气。任何帮助非常感谢。
=================================
编辑:
这确实会编译:
private IQueryable<T> Test<T>(IQueryable<T> temp1, IQueryable<T> temp2)
{
return temp1.Union(temp2); // compiles fine
}
然而,这并没有得到我真正的问题,这就是为什么扩展方法在泛型类型参数上无法识别的原因。这个解决方案简单地消除了(如上所述,大大简化)示例的关键点中的“泛型主义”。我认为,正如一个答案所指出的,IQueryable
和IQueryable<>
之间的区别确实很重要。
为了记录,我也尝试过:
private C<T> Test<C, T>(C<T> temp1, C<T> temp2) // The type parameter 'C' cannot be used with type arguments
{
return temp1.Union(temp2);
}
这会给出编译错误。
答案 0 :(得分:4)
代码无法编译,因为它无法编译:
IQueryable a, b;
a.Union(b);
因为Union
适用于IQueryable<T>
,而不是IQueryable
。
IQueryable<TItem> Test<T, TItem>(T temp1, T temp2) where T : IQueryable<TItem>
{
return temp1.Union(temp2);
}
您需要使其成为界面的通用版本并指定项目类型。返回类型不能为T
,因为Union
未返回T
,而是返回IQueryable<TItem>
。
事实上,我认为你的意思是:
IQueryable<TItem> Test<TItem>(IQueryable<TItem> temp1, IQueryable<TItem> temp2)
{
return temp1.Union(temp2);
}
哪个更简单。
答案 1 :(得分:1)
继承某些内容与实现某些内容之间存在差异,问题更像是您应该实现的composition over inheritance
IQueryable<T>
答案 2 :(得分:0)
我在这里想知道的根本问题是扩展方法未被识别的原因。感谢“usr”的回答,指出了方向。我没有考虑IQueryable
和IQueryable<T>
之间的区别。一旦我开始讨论这个问题,我就能找到我想要的真正答案,这似乎如下(再次,这是一个简单的实现,但它实现了我之后的原则):
private C Test<C, T>(C temp1, C temp2) where C : IQueryable<T>
{
return (C)temp1.Union(temp2); // compiles fine
}
感谢大家的帮助!