在这样的代码中:
if (insuranceNumberSearch == null
? true
: ei.InsuranceNumber.Contains(insuranceNumberSearch.Trim()))
doSomething();
其中insuranceNumberSearch
为null,其余表达式在以下代码中不为空:
var q = from ei in session.Linq<EmployeeInsurance>()
where insuranceNumberSearch == null
? true
: ei.InsuranceNumber.Contains(insuranceNumberSearch.Trim())
select ei;
无论insuranceNumberSearch为null还是非null,都会评估表达式的所有部分。
我正在使用LINQ to NHibernate
更新
不幸的是我把第一个片段弄错了。正确的是:
if (insuranceNumberSearch == null || (insuranceNumberSearch != null && ei.InsuranceNumber.Contains(insuranceNumberSearch.Trim()))
doSomething();
或
bool b1 = insuranceNumberSearch == null ? true : ei.InsuranceNumber.Contains(insuranceNumberSearch.Trim());
if (b1)
doSomething();
上述两个insuranceNumberSearch
为null
时,不再评估剩余的表达式。如果此类行为不存在,insuranceNumberSearch.Trim()
将导致引用对象为空异常。遗憾的是,即使insuranceNumberSearch
为null
并且导致错误,LINQ(或者LINQ-to-NHibernate)也不会遵循这样的好行为并评估所有表达式。
更新2:我发现了一个类似的问题:The || (or) Operator in Linq with C#
答案 0 :(得分:5)
打败我,但你不会使用
if (
(insuranceNumberSearch == null) ||
ei.InsuranceNumber.Contains(insuranceNumberSearch.Trim()))
doSomething();
在你的陈述中,是否在LINQ表达式中?
答案 1 :(得分:3)
如此代码所示,这不是LINQ的问题。此代码与您的代码类似,但它不会在LINQ表达式中评估条件的两端:
class Program
{
class MyClass
{
public string value;
public MyClass(string value) { this.value = value; }
public bool Contains(char elem)
{
Console.WriteLine("Checking if {0} contains {1}", value, elem);
return value.Contains(elem);
}
}
static void Main(string[] args)
{
var mc = new MyClass[2];
mc[0] = new MyClass("One");
mc[1] = new MyClass(null);
var q = from i in mc where i.value == null ? true : i.Contains('O') select i;
foreach (MyClass c in q)
Console.WriteLine(c.value == null ? "null" : c.value);
}
}
LINQ to NHibernate的表达式求值程序可能不像LINQ to Objects那样执行shotcut条件操作。
该计划的输出是:
Checking if One contains O
One
null
请记住,LINQ是一种表示任意表达式转换为其他语法的方法。据我了解,LINQ本身不会评估表达式,NHibernate会(不管是什么)。因此,LINQ只是将您提供的表达式转换为与NHibernate兼容的表达式。如果NHibernate没有表示快捷条件操作的方法,我可以想象出现的三件事之一:
答案 2 :(得分:2)
似乎问题出在LINQ的NHibernate提供程序中 - 对于LINQ to对象(它只是简单的查询到方法调用的语法转换),法律将按预期保持。问题是,当使用表达式树时,提供程序可以对您的代码进行任何修改。
更糟糕的是 - 目标执行环境可能不支持某些C#操作的确切语义。例如,它可能没有相同的浮点算术实现。
在您的示例中,似乎NHibernate不支持短路行为。我不清楚为什么这会是一个问题 - 它可以评估表达式的第二部分,但结果应该是相同的。
无论如何,如果短路运营商给提供商带来问题,您可能需要将查询分成两部分:
var q =
insuranceNumberSearch == null
? session.Linq<EmployeeInsurance>()
: (from ei in session.Linq<EmployeeInsurance>()
where ei.InsuranceNumber.Contains(insuranceNumberSearch.Trim())
select ei);