How to use LINQ Contains() to find a list of enums?

余生颓废 提交于 2019-12-05 02:12:54

Sure:

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

You could also define an extension method In() that would accept an object and a params array, and basically wraps the Contains function:

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

This allows you to specify the condition in a more SQL-ish way:

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

Understand that not all Linq providers like custom extension methods in their lambdas. NHibernate, for instance, won't correctly translate the In() function without additional coding to extend the expression parser, but Contains() works just fine. For Linq 2 Objects, no problems.

I have used this extension:

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

                     return list.Contains(value);           
    }

You may use this as the condition:

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

If that set of statuses has some meaning, for example those are statuses for accepted orders, you can define an extension method on your enum and use that in your linq query.

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;

Even if you could not give the method a simple name, you could still use something like IsValidThroughCompleted. In either case, it seems to convey a little more meaning this way.

Assumnig that the enum is defined in the order you specified in the question, you could shorten this by using an integer comparison.

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

This type of comparison though can be considered flaky. A simply re-ordering of enumeration values would silently break this comparison. I would prefer to stick with the more wordy version and probably clean up it up by refactoring out the comparison to a separate method.

You could put these in a collection, and use:

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

var results = Order.Status.Where(status => searchStatus.Contains(status));
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!