【问题标题】:Performing a LINQ query with optional search clauses使用可选搜索子句执行 LINQ 查询
【发布时间】:2011-03-17 02:26:41
【问题描述】:

我有一个页面,您可以在其中搜索人。他们可以获取所有人的列表,也可以按某些条件(例如名字或姓氏)对其进行过滤。

到目前为止,我一直在尝试使用this question 中详述的技术。

所以我的代码看起来像

string firstname=...
string lastname=...

var people=from p in People.All()
           where (firstname==null || firstname.ToLower()==p.FirstName.ToLower()) &&
                 (lastname==null || lastname.ToLower()==p.LastName.ToLower())
           select p;

在构建查询时出现空引用错误,但是当名字和姓氏都为空时。删除 where 子句可以消除错误。

为什么这不起作用? C# 是否尝试评估 where 子句每个部分的第二部分?这不应该是因为短路或对吗?

【问题讨论】:

  • 只有一个高代表用户 (79k) 在这里发布了答案。那个答案是正确的。你为什么删除它?
  • 'you' 在这种情况下是用户,显然删除了他们自己的答案。 IIRC,它谈到了使用 string.IsNullOrEmpty(firstname) 和 string.Equals()。我认为他删除了,因为他的回答没有解决你的实际问题,即使它有效

标签: c# linq short-circuiting


【解决方案1】:

使用字符串.Equals:

from p in People.All()
where (firstname == null || string.Equals (firstname, p.FirstName, StringComparison.InvariantCultureIgnoreCase)) &&
      (lastname == null || string.Equals (lastname, p.LastName, StringComparison.InvariantCultureIgnoreCase))
select p

这不仅避免了 null 问题,而且还强制您指定字符串比较类型(一件好事)。换言之,您可以指定在执行不区分大小写的比较时是使用特定于本地文化还是不变文化的规则。

【讨论】:

    【解决方案2】:

    你不需要调用 ToLower() 使用 string.compare 来代替 ignoreCase

    string.Compare(firstName, p.FirstName, true) 
    

    【讨论】:

      【解决方案3】:

      在调用 ToLower 之前确保它不为空:

      (firstname==null || (firstname!= null && firstname.ToLower()==p.FirstName.ToLower()))
      

      【讨论】:

        【解决方案4】:

        当两者都为空时它不起作用,因为语句的第一部分将评估为true,不允许评估短路。为什么不使用等价规则来翻转语句?

        (firstName != null && firstName.ToLower() == p.firstName.ToLower()) 
        

        编辑:我编写了以下内容并在 LINQPad 4 中成功运行,没有任何问题。我假设对People.All() 的调用只是返回一个带有完整记录集的IQueryable<People>?也许在这里发布您的异常文本,以便我们查看您是否无意中遗漏了什么?

        void Main()
        {
            string a = null;
            string b = null;
            var peeps = new List<Person> { 
                new Person { 
                    FirstName = "John",
                    LastName = "Connor"
                },
                new Person { 
                    FirstName = "Sarah",
                    LastName = "Connor",
                },
                new Person { 
                    FirstName = "Cletus",
                    LastName = "Handy"
                }
            };
        
            var somePeeps = from p in peeps
                where (a == null || a.ToLower() == p.FirstName.ToLower()) 
                    && (b == null || b.ToLower() == p.LastName.ToLower())
                select p;
        
            somePeeps.Dump();
        
        }
        
        public class Person
        {
            public string FirstName { get; set;}
            public string LastName { get; set;}
        }
        

        【讨论】:

        • 如果第一部分为真,那么它不应该评估第二部分,因为短路或虽然。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多