问题描述
我正在使用 linq 过滤选择的 MessageItem.我编写的方法接受一堆可能为空的参数.如果它们为空,则应忽略文件的标准.如果不为空,就用它来过滤结果.
I'm using linq to filter a selection of MessageItems. The method I've written accepts a bunch of parameters that might be null. If they are null, the criteria for the file should be ignored. If it is not null, use it to filter the results.
我的理解是在做 || 时操作是 C#,如果第一个表达式为真,则不应计算第二个表达式.
It's my understanding that when doing an || operation is C#, if the first expression is true, the second expression should not be evaluated.
例如
if(ExpressionOne() || ExpressionTwo())
{
// only ExpressionOne was evaluated because it was true
}
现在,在 linq 中,我正在尝试:
now, in linq, I'm trying this:
var messages = (from msg in dc.MessageItems
where String.IsNullOrEmpty(fromname) || (!String.IsNullOrEmpty(fromname) && msg.FromName.ToLower().Contains(fromname.ToLower()))
select msg);
我会认为这会是合理的,因为 String.IsNullOrEmpty(fromname)
将等于 true 和 || 的第二部分不会跑.
I would have thought this would be sound, because String.IsNullOrEmpty(fromname)
would equal true and the second part of the || wouldn't get run.
但是它确实运行了,第二部分
However it does get run, and the second part
msg.FromName.ToLower().Contains(fromname.ToLower()))
抛出一个空引用异常(因为fromname
为空)!!- 我收到一个经典的对象引用未设置为对象的实例"异常.
throws a null reference exception (because fromname
is null)!! - I get a classic "Object reference not set to an instance of an object" exception.
有什么帮助吗?
推荐答案
阅读本文档 解释了 linq 和 c# 如何断开连接.
Have a read of this documentation which explains how linq and c# can experience a disconnect.
由于希望将 Linq 表达式简化为普通方法以外的其他内容,因此您可能会发现此代码稍后在某些非 Linq to Objects 上下文中使用时会中断.
Since Linq expressions are expected to be reduced to something other than plain methods you may find that this code breaks if later it is used in some non Linq to Objects context.
说的是
String.IsNullOrEmpty(fromname) ||
( !String.IsNullOrEmpty(fromname) &&
msg.FromName.ToLower().Contains(fromname.ToLower())
)
格式错误,因为它应该是
Is badly formed since it should really be
String.IsNullOrEmpty(fromname) ||
msg.FromName.ToLower().Contains(fromname.ToLower())
这让你很清楚你依赖 msg 和 msg.FromName 都是非空的.
which makes it nice and clear that you are relying on msg and msg.FromName to both be non null as well.
为了让您在 C# 中的生活更轻松,您可以添加以下字符串扩展方法
To make your life easier in c# you could add the following string extension method
public static class ExtensionMethods
{
public static bool Contains(
this string self, string value, StringComparison comparison)
{
return self.IndexOf(value, comparison) >= 0;
}
public static bool ContainsOrNull(
this string self, string value, StringComparison comparison)
{
if (value == null)
return false;
return self.IndexOf(value, comparison) >= 0;
}
}
然后使用:
var messages = (from msg in dc.MessageItems
where msg.FromName.ContainsOrNull(
fromname, StringComparison.InvariantCultureIgnoreCase)
select msg);
然而这不是问题.问题在于系统的 Linq to SQL 方面正在尝试使用 fromname
值来构造发送到服务器的 query.
However this is not the problem. The problem is that the Linq to SQL aspects of the system are trying to use the fromname
value to construct the query which is sent to the server.
由于 fromname
是一个变量,所以翻译机制会关闭并执行要求的操作(即使它为 null,也会生成 fromname
的小写表示,这会触发例外).
Since fromname
is a variable the translation mechanism goes off and does what is asked of it (producing a lower case representation of fromname
even if it is null, which triggers the exception).
在这种情况下,您可以执行您已经发现的操作:保持查询原样,但确保您始终可以创建具有所需行为的非空 fromname 值,即使它为空.
in this case you can either do what you have already discovered: keep the query as is but make sure you can always create a non null fromname value with the desired behaviour even if it is null.
也许更好:
IEnumerable<MessageItem> results;
if (string.IsNullOrEmpty(fromname))
{
results = from msg in dc.MessageItems
select msg;
}
else
{
results = from msg in dc.MessageItems
where msg.FromName.ToLower().Contains(fromname)
select msg;
}
这并不是很好,因为查询包含其他约束,从而导致更多的重复,但对于简单的查询,实际上应该导致更易读/可维护的代码.如果您依赖匿名类型,这会很痛苦,但希望这对您来说不是问题.
This is not so great it the query contained other constraints and thus invovled more duplication but for the simple query actually should result in more readable/maintainable code. This is a pain if you are relying on anonymous types though but hopefully this is not an issue for you.
这篇关于||(或)C# 中的 Linq 运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!