如何组合两种通用方法

时间:2011-12-16 13:54:17

标签: c# entity-framework generics

我有两个扩展名:

public static IQueryable<T> Existing<T>(this IQueryable<T> qry) 
    where T : class, IDeletable
{
    return qry.Where(...);
}

public static IEnumerable<T> Existing<T>(this IEnumerable<T> qry) 
    where T : class, IDeletable
{
    return qry.Where(...);
}

如何将这两种方法合并为一种方法?我尝试了以下方法:

public static TU Existing<TU, T>(this TU qry)
    where TU : class, IQueryable<T>, IEnumerable<T>
    where T : class, IDeletable
{
    return (TU)qry.Where(...);
}

但这不起作用,因为无法正确推断类型(因为IQueryable继承自IEnumerable,我猜)。此外,T并不总是IQueryable,这似乎也是一个问题(问题:如果我在where子句中指定多个接口,那么不是以析取方式匹配的那些接口吗?)。在之前的情况下,如果适用IQuerable,则使用IEnumerable或{{1}}。我怎么能绕过这个?

2 个答案:

答案 0 :(得分:4)

您的尝试始终将其限制为IQueryable<T>实施。我假设你真的希望它适用于进程内查询和进程外查询。假设Where子句中的“...”是一个lambda表达式,你需要注意即使你在两个方法中都有相同的代码,编译器也会以非常不同的方式处理它们 - 因为它会已经应用了重载决策来确定要使用的Where实现。

我强烈建议你保留两个单独的重载原样。

答案 1 :(得分:2)

public static IQueryable<T> Existing<T>(this IEnumerable<T> qry) where T : class, IDeletable
{
    return qry.Where(/*...*/).AsQueryable();
}

在已经可查询的内容上调用AsQueryable将不会执行任何操作。另外,IQueryable继承自IEnumerable,所以首先:你可以将IQueryable传递给这个方法,第二个:结果实际上是IEnumerable和IQueryable。