C# 为什么这是易读的。在哪里<;t来源>;调用返回与IQueryable不同的类型<;t来源>;?

C# 为什么这是易读的。在哪里<;t来源>;调用返回与IQueryable不同的类型<;t来源>;?,c#,generics,linq-to-sql,iqueryable,C#,Generics,Linq To Sql,Iqueryable,这将有点难以解释,并提供代码示例,所以请容忍我,如果我不清楚,请提问 解释 在这种情况下,我将一个IQueryable(使用LINQ to SQL)传递到一个泛型方法中,然后在IQueryable的副本上调用一个.where。泛型方法可以由两个不同的代码路径中的任何一个调用。在其中一个代码路径中,IQueryable的.ElementType在调用Where后发生更改,但在另一个路径中保持不变。在它改变的情况下我会出错,我需要它不要这样做 代码 我有一个名为InventoryGridQueryE

这将有点难以解释,并提供代码示例,所以请容忍我,如果我不清楚,请提问

解释 在这种情况下,我将一个
IQueryable
(使用LINQ to SQL)传递到一个泛型方法中,然后在
IQueryable
的副本上调用一个
.where
。泛型方法可以由两个不同的代码路径中的任何一个调用。在其中一个代码路径中,
IQueryable
.ElementType
在调用
Where
后发生更改,但在另一个路径中保持不变。在它改变的情况下我会出错,我需要它不要这样做

代码 我有一个名为
InventoryGridQueryElement
的类型,它继承自
PivotGridQueryElement
,大致如下:

public class InventoryGridQueryElement : PivotGridQueryElement {

    public int IId { get; set; }

    ... other simple public properties
}
另一个类创建一个
IQueryable
。在一个产生问题的执行路径中,该对象保存在
对象
变量中,然后该变量被传递到泛型方法中。在另一个执行路径中,传递到泛型方法的变量仍然是
IQueryable

两个执行路径首先调用此方法,并将
IQueryable
(或
对象
)作为
数据源
参数传入:

protected DataTableAndPaging FilterDataSource<T>( IQueryable<T> dataSource, NameValueCollection queryString ) where T : PivotGridQueryElement {
i、 e

实际问题 这两行中的第二行,带有
copy.Where
,是出现问题的地方。在有问题的执行路径中,如果我在
copy.ElementType
上设置了一个监视,那么在执行这一行之前

+       copy.ElementType    {Name = "InventoryGridQueryElement" FullName = "ProjectNamespace.Models.GridModelInventory+InventoryGridQueryElement"}  System.Type {System.RuntimeType}
+       copy.ElementType    {Name = "PivotGridQueryElement" FullName = "ProjectNamespace.Models.PivotGridQueryElement"} System.Type {System.RuntimeType}
但当我跨过这条线之后

+       copy.ElementType    {Name = "InventoryGridQueryElement" FullName = "ProjectNamespace.Models.GridModelInventory+InventoryGridQueryElement"}  System.Type {System.RuntimeType}
+       copy.ElementType    {Name = "PivotGridQueryElement" FullName = "ProjectNamespace.Models.PivotGridQueryElement"} System.Type {System.RuntimeType}
在另一个执行路径中,一切正常,我在执行
copy.where
行之前和之后都有第一个监视结果

一旦实际进行了查询,就会抛出一个错误,因为查询涉及
InventoryGridQueryElement
.IId
属性,但
PivotGridQueryElement
没有此类属性

更新:

我决定尝试另一种方法来跟踪
T
的类型,而不是观看
IQueryable.ElementType
。我切换到本地人窗口,查看每个副本和iQ的类型。iQ和copy在问题路径中都列为
IQueryable
,即使iQ.ElementType和copy.ElementType都是
InventoryGridQueryElement
。在成功路径中,它们都列为
IQueryable

然后,我在查询前后添加了以下行:

Type copyType1 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType1 = copy.ElementType;

copy = copy.Where( pgr1 => iQ.Where( pgr2 => pgr2.Key == pgr1.Key && pgr2.DataField == column.DataField && pgr2.ColumnText.Contains( requestValue ) ).Any() );

Type copyType2 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType2 = copy.ElementType;
在好的路径中,
copyType1
=
elementType1
=
copyType2
=
elememtype2
=
InventoryGridQueryElement

在错误路径中,
copyType1
=
elementType1
=
InventoryGridQueryElement
,但
copyType2
=
elementType2
=
PivotGridQueryElement

再次更新:

我编写了一个简短的独立控制台程序来重现这个问题。我要求只参考那个例子,而不考虑这个问题对复杂的
.Where
查询或LINQ to SQL的额外关注

问题: 那么,
.Where
调用更改
IQueryable
ElementType
可能出于什么原因?这些原因是否与我的具体情况有关


注意:此代码与我们正在使用的第三方API紧密耦合。我不喜欢API的编写方式,正因为如此,这个可查询的对象才会存储在泛型对象中。

在有问题的执行路径中,当您到达该行时,
t
是什么?当计算
时,如果
T
被解释为
PivotGridQueryElement
,则我能够导致相同的行为。事实上,这里有一个简单的单行演示:
var iQ2=((IQueryable)iQ)。Select(s=>s)
现在将
ElementType
作为
PivotGridQueryElement
进行计算,但我不太清楚为什么。@mellamokb在两条路径中都是InventoryGridQueryElement,直到那一行,然后在其中一条路径中切换。在您的示例中,您使用了
Queryable。选择
,它返回
IQueryable
,它可能与
IQueryable
的类型相同,也可能不同,因此,我并不比
Queryable时感到惊讶。Where
返回一个
IQueryable
,它与
IQueryable
@mellamokb Jon Skeet为我的相关问题提供了一个不同的类型。
Type copyType1 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType1 = copy.ElementType;

copy = copy.Where( pgr1 => iQ.Where( pgr2 => pgr2.Key == pgr1.Key && pgr2.DataField == column.DataField && pgr2.ColumnText.Contains( requestValue ) ).Any() );

Type copyType2 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType2 = copy.ElementType;