C# IEnumerable<;T>;和IQueryable<;T>;

C# IEnumerable<;T>;和IQueryable<;T>;,c#,generics,C#,Generics,我试图为IEnuemrable和IQueryable 像这样: public T Paginate<T, TS>(T list) where T : IEnumerable<TS> { CheckValidityAndClamp(); return (T)(list.Skip(Page*PageSize).Take(PageSize)); } public T分页(T列表),其中T:IEnumerable { 检查有效性和指示灯(); return(T)

我试图为
IEnuemrable
IQueryable

像这样:

public T Paginate<T, TS>(T list) where T : IEnumerable<TS>
{
    CheckValidityAndClamp();
    return (T)(list.Skip(Page*PageSize).Take(PageSize));
}
public T分页(T列表),其中T:IEnumerable
{
检查有效性和指示灯();
return(T)(list.Skip(Page*PageSize.Take(PageSize));
}
当我传入一个
列表
实例时,它编译得很好。 但运行时会出现强制转换异常:

System.InvalidCastException : An object of type '<TakeIterator>d__3a`1[System.Int32]' can not be converted to the type 'System.Collections.Generic.List`1[System.Int32]'.
System.InvalidCastException:类型为“d_u3a`1[System.Int32]”的对象无法转换为类型为“System.Collections.Generic.List`1[System.Int32]”。

为什么呢?
List
实现了
IEnumerable
,那么为什么会出现强制转换异常?

您没有返回列表
Take
是用迭代器块实现的,这意味着实际类型是一个没有编译时标识符的类型(这就是为什么它看起来很奇怪),并且它实现了
IEnumerable
。它不是您试图将其强制转换到的
列表


除此之外,您的方法实际上无法用于任何
IQueryable
对象。它调用
Skip
的实现,该实现接受
IEnumerable
(因为这是泛型约束告诉编译器它必须实现的),因此如果它是
IQueryable
(即使解决了混乱的cast问题),也不会使用查询提供程序来翻译
Skip
调用。这里需要有两个重载,一个用于
IQueryable
,另一个用于
IEnumerable
;考虑到您需要调用两个
Skip
Take
方法,一个用于
IEnumerable
IQueryable
您没有返回列表,这是问题的本质
Take
是用迭代器块实现的,这意味着实际类型是一个没有编译时标识符的类型(这就是为什么它看起来很奇怪),并且它实现了
IEnumerable
。它不是您试图将其强制转换到的
列表

除此之外,您的方法实际上无法用于任何
IQueryable
对象。它调用
Skip
的实现,该实现接受
IEnumerable
(因为这是泛型约束告诉编译器它必须实现的),因此如果它是
IQueryable
(即使解决了混乱的cast问题),也不会使用查询提供程序来翻译
Skip
调用。这里需要有两个重载,一个用于
IQueryable
,另一个用于
IEnumerable
;考虑到您需要调用两个
Skip
Take
方法,这是问题的本质,一个用于
IEnumerable
IQueryable
来扩展Servy(正确)的答案-另一个问题是
Skip
Take
是扩展方法,这是调用静态方法的语法糖。由于静态方法是在编译时绑定的,编译器拥有的最佳信息是
T
IEnumerable
,因此编译器将
Skip
Take
绑定到
可枚举的静态方法。无法在运行时动态绑定静态方法。这就是为什么在
IEnumerable
IQueryable
上有两个不同的扩展方法类(
Enumerable
Queryable

您需要两个重载。

来扩展Servy(正确)的答案-另一个问题是
Skip
Take
是扩展方法,这是调用静态方法的语法糖。由于静态方法是在编译时绑定的,编译器拥有的最佳信息是
T
IEnumerable
,因此编译器将
Skip
Take
绑定到
可枚举的静态方法。无法在运行时动态绑定静态方法。这就是为什么在
IEnumerable
IQueryable
上有两个不同的扩展方法类(
Enumerable
Queryable


您需要两个重载。

由于无法将IEnumerable强制转换为List(这就是为什么LINQ具有.ToList()扩展名)。我想你想要的是这样的:

public IEnumerable<T> Paginate<T>(IEnumerable<T> list)
{
    return list.Skip(Page * PageSize).Take(PageSize);
}
IEnumerable<int> list = someQueryResult;
IEnumerable<int> page = class.Paginate<int>(list);
public IEnumerable分页(IEnumerable列表)
{
返回列表。跳过(页面*页面大小)。获取(页面大小);
}
它将与实现IEnumerable(List,T[],IQueryable)的任何源一起使用

你可以这样称呼它:

public IEnumerable<T> Paginate<T>(IEnumerable<T> list)
{
    return list.Skip(Page * PageSize).Take(PageSize);
}
IEnumerable<int> list = someQueryResult;
IEnumerable<int> page = class.Paginate<int>(list);
IEnumerable list=someQueryResult;
IEnumerable page=class.Paginate(列表);

正如其他答案所指出的那样。IQueryable有自己的一组扩展方法。因此,尽管这样做可行,但分页不会作为数据源进行,因为它将使用IEnumerable扩展名,因为无法将IEnumerable强制转换为List(这就是为什么LINQ具有.ToList()扩展名)。我想你想要的是这样的:

public IEnumerable<T> Paginate<T>(IEnumerable<T> list)
{
    return list.Skip(Page * PageSize).Take(PageSize);
}
IEnumerable<int> list = someQueryResult;
IEnumerable<int> page = class.Paginate<int>(list);
public IEnumerable分页(IEnumerable列表)
{
返回列表。跳过(页面*页面大小)。获取(页面大小);
}
它将与实现IEnumerable(List,T[],IQueryable)的任何源一起使用

你可以这样称呼它:

public IEnumerable<T> Paginate<T>(IEnumerable<T> list)
{
    return list.Skip(Page * PageSize).Take(PageSize);
}
IEnumerable<int> list = someQueryResult;
IEnumerable<int> page = class.Paginate<int>(list);
IEnumerable list=someQueryResult;
IEnumerable page=class.Paginate(列表);

正如其他答案所指出的那样。IQueryable有自己的一组扩展方法。因此,尽管这一切都会起作用,但分页不会作为数据源进行,因为它将使用IEnumerable扩展名

您可以显示调用代码吗?您可以显示调用代码吗?它将进行编译,但不会绑定到
IQueryable
扩展方法。我已经更新,使它更清楚,但它将编译和运行。但它不会非常有效,因为它会减少