提问人:Joseph Morgan 提问时间:10/28/2023 更新时间:10/28/2023 访问量:63
编写可在任何 IEnumerable(包括 IQueryable)上调用的泛型扩展方法的正确方法是什么?
What's the correct way to write a generic extension method that can be called on any IEnumerable (including an IQueryable)?
问:
我有一些静态函数,它们封装了我们执行的常见数据库操作。
例:
public static IQueryable<Round> FilterByStandardExclusionCriteria(
this IQueryable<Round> rounds,
bool someExclusionFlag = true,
bool otherExclusionFlag = true,
)
{
return (
from round in rounds
where (
// Filter down the list of rounds based on exclusion flags
)
select round
);
}
这通常工作得很好,但有时 LINQ 到 SQL 的转换会失败,我们必须在调用某些函数之前显式启用对 LINQ 查询的客户端计算。
我将扩展方法重写为泛型,最终看起来像这样:
public static T FilterByStandardExclusionCriteria<T>(
this T rounds,
bool someExclusionFlag = true,
bool otherExclusionFlag = true,
) where T : IEnumerable<Round>
{
return (
from round in rounds
where (
// Filter down the list of rounds based on exclusion flags
)
select round
);
}
但是这样做会给我一个编译器错误,说
无法将类型“System.Collections.Generic.IEnumerable<Namespace.Round>”隐式转换为“T”。
我试图用 显式将返回值转换为 T,但这样做会导致在运行时抛出以下异常:(T)return ...
引发异常:“System.Private.CoreLib.dll 中的”System.InvalidCastException“:”无法将类型为'WhereEnumerableIterator'1[Namespace.Round]'的对象强制转换为类型'Microsoft.EntityFrameworkCore.DbSet'1[Namespace.Round]'。
编写可在任何 IEnumerable 上调用的泛型扩展方法的正确方法是什么?
答:
0赞
pakeha_by
10/28/2023
#1
您可以保持原样(使用 IQueryable 类型)并按如下方式调用它:FilterByStandardExclusionCriteria
enumerableCollection.AsQueryable().FilterByStandardExclusionCriteria()
评论
0赞
Joseph Morgan
10/28/2023
哦,哇,刚刚调查了一下。似乎正是我需要的。总的来说,我很好奇为什么泛型方法不起作用。如果查询语句返回与输入相同的类型,而输入保证与返回类型相同,为什么还需要强制转换返回结果?
0赞
pakeha_by
10/28/2023
如果您将其声明为public static IEnumerable<T> FilterByStandardExclusionCriteria<T>( this IEnumerable<T> rounds...
评论
IQueryable<T>
IEnumerable<T>
Expression<Func<>>
Func<>
Func<>