过滤列表中的可空项目 - LINQ

时间:2018-06-06 16:25:37

标签: c# linq

我有以下列表项目才能显示。我可以看到下面的小列表,可能是数百行。 StartDate以及EndDate可以是nullable,如果EndDate为空,则表示课程仍然开放。

CourseId    ClassName    StartDate   EndDate      isActiveinDB
--------    ---------    ---------   -------      ------------
12321       Math         08-25-2017  12-02-2017      Y
32342       Math         08-25-2017  12-02-2017      N
25325       Math         01-25-2018     -            Y

如果我在今天的日期(06-06-2018)通过以下方法,则返回所有课程,而不仅仅是最后一门课程(数学25325),该课程尚未过期并基于isActiveinDB打开。< / p>

我想知道以下实施中的不正确之处。

public List<Courses> GetClassesByDate( DateTime date, List<Courses> allCourses)
{
   List<Courses> courses  = allCourses.Where( x => x.StartDate.HasValue ? x.StartDate <= date : true 
                            && x.EndDate.HasValue ? x.EndDate.Value >= date : true 
                            && x.isActiveinDB.Equals("Y")).ToList();
   return courses;
}

感谢@DavidG,实现在以下link

2 个答案:

答案 0 :(得分:5)

尝试(如果StartDate可以为空,正如您所说):

List<Courses> courses  = allCourses.Where( x =>  
                        (x.StartDate.HasValue ? x.StartDate.Value <= date : true)
                        && (x.EndDate.HasValue ? x.EndDate.Value >= date : true) 
                        && x.isActiveinDB.Equals("Y")).ToList();

您看到我添加了()了吗?我在做什么,实际上是

x.EndDate.HasValue ? x.EndDate.Value : (true && isActiveinDB.Equals("Y"))
你知道吗? true不是单个值,而是子表达式true && isActiveinDB.Equals("Y")

答案 1 :(得分:1)

运算符按顺序在表达式中求值。它在https://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx中进行了解释。这是一个表格,用于在表格中按顺序显示运营商。

正如您在列表中看到的那样,条件表达式(?:)的优先级非常低。因此,我建议在条件表达式周围放置括号,然后就可以避免出现这种意外。

以下代码是用于验证运营商订单的NUnit测试代码。希望记录类接近您的情况。

执行此测试时,第一个断言通过,但第二个断言失败。它证明括号在这种表达方式上有所不同。

[TestFixture]
public class SyntaxTest
{
    public class Record
    {
        public string Id;
        public DateTime? StartDate;
        public DateTime? EndDate;
        public string isActiveinDB;
    }

    [TestCase]
    public void TestConditionalSyntax()
    {
        var list = new List<Record>
        {
            new Record { Id = "0000", StartDate = DateTime.Parse("2018-01-01"), EndDate = DateTime.Parse("2018-06-01"), isActiveinDB = "Y" },
            new Record { Id = "0001", StartDate = DateTime.Parse("2018-01-01"), EndDate = DateTime.Parse("2018-09-01"), isActiveinDB = "N" },
            new Record { Id = "0002", StartDate = DateTime.Parse("2018-01-01"), EndDate = DateTime.Parse("2018-08-01"), isActiveinDB = "Y" },
            new Record { Id = "0003", StartDate = DateTime.Parse("2018-01-01"), EndDate = null, isActiveinDB = "Y" },
            new Record { Id = "0004", StartDate = DateTime.Parse("2018-08-01"), EndDate = null, isActiveinDB = "Y" },
            new Record { Id = "0005", StartDate = null, EndDate = DateTime.Parse("2018-06-01"), isActiveinDB = "Y" },
            new Record { Id = "0006", StartDate = null, EndDate = DateTime.Parse("2018-08-01"), isActiveinDB = "Y" },
        };

        var date = DateTime.Parse("2018-06-15");
        var result1 = list.Where(x => ( x.StartDate.HasValue ? x.StartDate <= date : true )
                                 && ( x.EndDate.HasValue ? x.EndDate >= date : true )
                                 && x.isActiveinDB.Equals("Y")).ToList();
        Assert.That(result1.Count, Is.EqualTo(3));

        var result2 = list.Where(x => x.StartDate.HasValue ? x.StartDate <= date : true
                                 && x.EndDate.HasValue ? x.EndDate >= date : true
                                 && x.isActiveinDB.Equals("Y")).ToList();
        Assert.That(result2.Count, Is.EqualTo(3));
    }
}