通过 DataContext 使用数据库。
有这样的操作:
var flat = StavRealtyDb.TargetFlat
.Where(x => true || _some condition_).ToList();
因此,如果条件的第一部分为true,则编译器应该跳过第二部分,对吧? 但这并没有发生。如果有.ToArray(),也会发生同样的问题。
但是,如果最终不是 .ToList 或 .ToArray 之类的内容 - 编译器将跳过条件的第二部分。
有什么问题吗?正常吗? :)
更新
好的,谢谢您的解答!我明白这是正常的。但问题是条件的第一部分包含: someobject == null;第二部分包含:someobject.Contains()。
.Where(x => someobject == null || someobject.Field.Contains(x.somefield))
所以当 someobject == null 时我有 ArgumentNullException (我希望第一部分将返回 true 而第二部分将不会执行)。你能告诉我,我该如何解决这个问题吗?
P.S:实际上,.Where() 表达式更复杂:
.Where(x=> (part1 || part 2) && (part1 || part2) && ......)
最佳答案
您正在 IQueryable
上执行 Where
,并且参数是 Expression
而不是 Func
http://msdn.microsoft.com/en-us/library/vstudio/bb535040%28v=vs.100%29.aspx
Expression
只是传递给底层 Where
实现。
我发现这个主题很有趣,所以我创建了一个示例。假设我们有以下代码:
using System;
using System.Linq.Expressions;
namespace TestApplication
{
class CompilerTest
{
public void Test()
{
Func<bool> func = () => true || Foo();
Expression<Func<bool>> expr = () => true || Foo();
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
}
}
我们构建它(发布构建),反编译的代码如下所示:
using System;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace TestApplication
{
internal class CompilerTest
{
[CompilerGenerated]
private static Func<bool> CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1;
public CompilerTest()
{
base.\u002Ector();
}
public void Test()
{
if (CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1 == null)
{
// ISSUE: method pointer
CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1 = new Func<bool>((object) null, __methodptr(\u003CTest\u003Eb__0));
}
Func<bool> func = CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1;
(Expression<Func<bool>>) (() => true || CompilerTest.Foo());
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
[CompilerGenerated]
private static bool \u003CTest\u003Eb__0()
{
return true;
}
}
}
如果我们隐藏编译器生成的代码(dotPeek 选项),它看起来像这样:
using System;
using System.Linq.Expressions;
namespace TestApplication
{
internal class CompilerTest
{
public void Test()
{
Func<bool> func = (Func<bool>) (() => true);
(Expression<Func<bool>>) (() => true || CompilerTest.Foo());
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
}
}
正如我们所看到的,lambda 中指定的 Func 代码已被优化(如果编译器对其进行了优化,这才是真正的问题)。表达式中指定的代码显然没有优化(因为它是一个表达式,所以从编译器的角度来看,此时没有什么可以优化的)。
关于c# - 最后添加 .ToList(或 ToArray)时出现 LINQ 'OR' 条件问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27514427/