该|| (或)运算符Linq中使用C#运算符、Linq

2023-09-02 10:38:33 作者:岔开双腿秀贞操

我使用LINQ to过滤选择MessageItems的。我写的方法接受了一堆可能是空的参数。如果它们是空值,则标准的文件应该被忽略。如果不为空,用它来筛选结果。

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#,如果第一前pression为真时,第二前pression不应被评价。

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)就等于真实的第二部分||不会得到运行。

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 为null)! - 我得到一个典型的未将对象引用设置到对象的实例异常

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的EX pressions预计将减少到比普通方法,其他的东西你可能会发现,如果后面的code中断它是用在一些非LINQ到对象上下文。

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.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 值来构造的查询的被发送到服务器。

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 是一个变量的转换机制熄灭,做什么是要求它(产生较低的情况下,再的presentation 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;    
}

这是没有那么大它的查询中包含其他方面的限制,因此invovled更多的重复,但对于简单的查询,其实应该导致更可读/维护code。这是,如果你依靠匿名类型虽然是痛苦的,但希望这不是你的问题。

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.