C# 如何结合两种通用方法

C# 如何结合两种通用方法,c#,entity-framework,generics,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

我有两个分机:

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(...);
}
现有公共静态IQueryable(此IQueryable qry)
其中T:类,可识别
{
返回qry.Where(…);
}
现有公共静态IEnumerable(此IEnumerable qry)
其中T:类,可识别
{
返回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(...);
}
public static TU Existing(此TU qry)
其中TU:class,IQueryable,IEnumerable
其中T:类,可识别
{
返回(TU)数量,其中(…);
}
但这不起作用,因为无法正确推断类型(我想是因为IQueryable继承了IEnumerable)。此外,
T
并不总是
IQueryable
,这在这里似乎也是个问题(问题:如果我在where子句中指定多个接口,这些接口不是以析取方式匹配的吗?)。在前一种情况下,如果合适,则使用
IQuerable
,否则使用
IEnumerable
。如何规避此问题?

您的尝试总是将其限制在
IQueryable
实现中。我假设您确实希望它同时适用于进程内查询和进程外查询。假设
Where
子句中的“…”是lambda表达式,您需要注意,即使两种方法中的代码相同,编译器处理它们的方式也会非常不同,因为它已经应用了重载解析来确定要使用的
Where
实现

我强烈建议您保留这两个单独的重载。

公共静态IQueryable存在(此IEnumerable qry),其中T:class,IDeletable
public static IQueryable<T> Existing<T>(this IEnumerable<T> qry) where T : class, IDeletable
{
    return qry.Where(/*...*/).AsQueryable();
}
{ 返回qry.Where(/*…*/).AsQueryable(); }

对已可查询的内容调用
AsQueryable
,将不会起任何作用。此外,IQueryable继承自IEnumerable,因此首先:您可以将IQueryable传递给此方法,其次:结果实际上是一个IEnumerable和一个IQueryable。

为什么它总是将其限制为
IQueryable
?如果where子句中有多个接口,那么这些接口不是以析取方式匹配的吗?如果不是
IQueryable
,为什么不能只匹配
IEnumerable
?@duedl0r:不,如果有多个接口约束,则类型参数必须满足所有约束。因此,指定
IEnumerable
实际上是多余的。参见C#4规范的第4.4.4节:“如果给定的类型参数不满足一个或多个类型参数的约束,则会发生编译时错误。”如果有,则标记为答案。;)