代码之家  ›  专栏  ›  技术社区  ›  Todd Davis

如何使用LINQ Contains()查找枚举列表?

  •  9
  • Todd Davis  · 技术社区  · 14 年前

    OrderStatus ,它包含订单可以处于的各种状态:

    • 创建
    • 等待
    • 有效
    • 处理
    • 完整的

    我要做的是创建一个LINQ语句,它将告诉我OrderStaus是有效的、活动的、已处理的还是已完成的。

    var status in Order.Status.WHERE(status => 
          status.OrderStatus == OrderStatus.Valid || 
          status.OrderStatus == OrderStatus.Active|| 
          status.OrderStatus == OrderStatus.Processed|| 
          status.OrderStatus == OrderStatus.Completed)
    

    这很管用,但很“罗嗦”。有没有办法把这个转换成 Contains() 陈述和缩短一点?

    5 回复  |  直到 14 年前
        1
  •  16
  •   KeithS    7 年前

    当然:

    var status in Order.Status.Where(status => new [] {
            OrderStatus.Valid, 
            OrderStatus.Active, 
            OrderStatus.Processed,
            OrderStatus.Completed
        }.Contains(status.OrderStatus));
    

    还可以定义扩展方法 In()

    public static bool In<T>(this T theObject, params T[] collection)
    {
        return collection.Contains(theObject);
    }
    

    这允许您以更SQL的方式指定条件:

    var status in Order.Status.Where(status => 
        status.OrderCode.In(
            OrderStatus.Valid, 
            OrderStatus.Active, 
            OrderStatus.Processed,
            OrderStatus.Completed));
    

    要知道并不是所有的Linq提供者都喜欢lambdas中的自定义扩展方法。例如,NHibernate如果没有额外的代码来扩展表达式解析器,就不能正确地转换In()函数,但是Contains()工作得很好。对于Linq 2对象,没有问题。

        2
  •  3
  •   Aliostad    14 年前

        public static bool IsIn<T>(this T value, params T[] list)
        {
    
                         return list.Contains(value);           
        }
    

    您可以将此作为条件:

       Where(x => x.IsIn(OrderStatus.Valid, ... )
    
        3
  •  1
  •   Jeff Ogata    14 年前

    如果这组状态具有某种意义,例如,它们是已接受订单的状态,则可以在枚举上定义扩展方法,并在linq查询中使用该方法。

    public static class OrderStatusExtensions
    {
        public static bool IsAccepted(this OrderStatuses status)
        {
            return status == OrderStatuses.Valid
                || status == OrderStatuses.Active
                || status == OrderStatuses.Processed
                || status == OrderStatuses.Completed;
        }
    }
    
    var acceptedOrders = from o in orders
                         where o.Status.IsAccepted()
                         select o;
    

    IsValidThroughCompleted . 无论是哪种情况,它似乎都以这种方式传达了更多的含义。

        4
  •  0
  •   JaredPar    14 年前

    如果枚举是按照您在问题中指定的顺序定义的,则可以使用整数比较来缩短它。

    var result = 
      Order.Status.Where(x => 
        (int)x >= (int)OrderStatus.Valid &
        & (int)x <= (int)OrderStatus.Completed);
    

    但这种比较可以被认为是不可靠的。对枚举值进行简单的重新排序将无声地打破这种比较。我更愿意坚持使用更冗长的版本,并可能通过重构与单独方法的比较来清理它。

        5
  •  0
  •   Reed Copsey    14 年前

    你可以把这些放在一个集合中,并使用:

    OrderStatus searchStatus = new[] {
                    OrderStatus.Valid,
                    OrderStatus.Active,
                    OrderStatus.Processed,
                    OrderStatus.Completed };
    
    var results = Order.Status.Where(status => searchStatus.Contains(status));