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

时间:2010-10-27 15:31:18

标签: c# .net linq contains

我有一个名为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 个答案:

答案 0 :(得分:16)

不确定

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

您还可以定义一个接受对象和params数组的扩展方法In(),并基本上包装Contains函数:

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

这允许您以更多SQL-ish方式指定条件:

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

了解并非所有Linq提供商都喜欢他们的lambda中的自定义扩展方法。例如,NHibernate将无法正确转换In()函数而无需额外编码来扩展表达式解析器,但Contains()可以正常工作。对于Linq 2对象,没问题。

答案 1 :(得分:2)

我使用过这个扩展程序:

    public static bool IsIn<T>(this T value, params T[] list)
    {

                     return list.Contains(value);           
    }

您可以将此作为条件:

   Where(x => x.IsIn(OrderStatus.Valid, ... )

答案 2 :(得分:1)

如果这组状态具有某些含义,例如那些是接受订单的状态,您可以在枚举上定义扩展方法并在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之类的东西。在任何一种情况下,它似乎都以这种方式表达了更多的含义。

答案 3 :(得分:0)

根据您在问题中指定的顺序来定义枚举,您可以通过使用整数比较来缩短它。

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

这种比较虽然可以被认为是片状的。简单地重新排序枚举值会默默地破坏这种比较。我宁愿坚持使用更多罗嗦的版本,也可能通过将比较重构为单独的方法来清理它。

答案 4 :(得分:0)

您可以将它们放入集合中,然后使用:

OrderStatus searchStatus = new[] {
                OrderStatus.Valid,
                OrderStatus.Active,
                OrderStatus.Processed,
                OrderStatus.Completed };

var results = Order.Status.Where(status => searchStatus.Contains(status));