在LINQ中,强制转换与内部选择之间的区别

Dav*_*gel 12 c# linq entity-framework

此代码抛出异常:

var query = services
             .SomeQuery(bar).select(x => (Foo)x)
             .Where(x.PropertyOfFoo == FooState.SomeState);
var result = query.ToList(); 
Run Code Online (Sandbox Code Playgroud)

例外:

Unable to cast the type...
LINQ to Entities only supports casting EDM primitive or enumeration types.
Run Code Online (Sandbox Code Playgroud)

此代码有效:

var query = services
             .SomeQuery(bar).select(x => x as Foo)
             .Where(x.PropertyOfFoo == FooState.SomeState);
var result = query.ToList(); 
Run Code Online (Sandbox Code Playgroud)

为什么as允许转换而cast不是?

据我所知,as如果任一调用失败,将返回null并且cast会抛出异常.好的.但是当我运行这段代码时:

var query = services
             .SomeQuery(bar);
var result = query.ToList(); 
Run Code Online (Sandbox Code Playgroud)

我得到了更大的查询结果.为什么?

The*_*kis 7

LINQ to Entities与LINQ to Objects不同.虽然LINQ to Objects函数可以接受任何匹配的委托并盲目地将其作为普通的C#代码调用,但LINQ to Entities将您的lambdas视为表达式树,因为它需要理解这些lambdas的语义(不仅仅是它们的签名)并将它们转换为等价物查询您的EF后端.当然,这意味着LINQ to Entities无法处理LINQ to Objects可以执行的所有操作.

现在,正如您所说的,转换和使用之间的一个区别as是,转换会在失败和as返回时抛出异常null.但是两者之间存在更重要的区别:演员表将应用任何潜在的自定义显式转换,而as只是尝试将引用重新解释为其他内容,忽略任何潜在的转换.

正如您所理解的,转换比复杂得多as,因为转换可能会调用explicit operatorLINQ提供程序无法轻松解析的自定义方法().提供者可能根本无法检查潜在自定义转换的代码(我对表达式树的限制知之甚少),更不用说为底层源转换它了.因此,LINQ to Entities选择仅允许as和最简单的转换情况(基本上,它允许提前知道转换逻辑并且不可能是自定义用户代码的情况).