Shahar Shokrani
Shahar Shokrani

Reputation: 8752

Filtering Linq based on Enum, with a specific unique value exception

In order to simplify, let say I have MyEnum and MyClass:

enum MyEnum
{
    Undefined = 0,
    A = 1,
    B = 2,
    C = 3,
    D = 4
}

class MyClass { MyEnum MyEnumValue { get; set; } }

In order to filter a list of MyClass by a MyEnum value I'm using:

list.Where(r => r.MyEnumValue == myEnum);

But if the MyEnum is equal to specific value (lets say MyEnum.B) I would need the list to return also any values that equal to MyEnum.B or MyEnum.A.

This is what I've came up with:

public static MyClass MyClass_By_MyEnum(IEnumarable<MyClass> list, MyEnum myEnum)
{
    if (myEnum == MyEnum.B)
    {
        return list.Where(r =>
                        r.MyEnumValue == MyEnum.A || 
                        r.MyEnumValue == MyEnum.B ||
                        r.MyEnumValue == MyEnum.C
                    ).FirstOrDefault();
    }
    else
    {
        return list.Where(r => r.MyEnumValue == myEnum).FirstOrDefault();
    }
}

Is there any way achieving this using one line only? without the if else statement?

EDIT 1: I'm searching for a better design based solution, any suggestion?

Upvotes: 0

Views: 945

Answers (4)

Prasad Telkikar
Prasad Telkikar

Reputation: 16049

what about !=

 return list.Where(r =>
                        r.MyEnumValue != MyEnum.Undefined  || 
                        r.MyEnumValue != MyEnum.D
                    ).FirstOrDefault();

In real case we can take less elements in lookFor array and use negation, something like

var lookFor = new [] { MyEnum.Undefined, MyEnum.D};
return list.FirstOrDefault(r => !lookFor.Contains(r.MyEnumValue));

Please check negation in FirstOrDefault query, this will help us to reduce elements in loofFor array

Upvotes: 1

Shahar Shokrani
Shahar Shokrani

Reputation: 8752

Ended up mixing @john-wu and @botz3000 answers with:

var lookFor = new [] { MyEnum.A, MyEnum.B, MyEnum.C };

list.FirstOrDefault(r => r.MyEnumValue == myEnum || (
                             myEnum == MyEnum.B && lookFor.Contains(r.MyEnumValue)
                         )
                    );

Upvotes: 0

John Wu
John Wu

Reputation: 52240

Use an array. Also, you don't need to use Where since you can pass the delegate to FirstOrDefault.

var lookFor = new [] { MyEnum.A, MyEnum.B, MyEnum.C };
return list.FirstOrDefault(r => lookFor.Contains(r.MyEnumValue));

Upvotes: 4

Botz3000
Botz3000

Reputation: 39610

This is the shortest I can think of. Not sure if that makes the intent much clearer however.

list.Where(r => r.MyEnumValue == myEnum || (myEnum == MyEnum.B && r.MyEnumValue == MyEnum.A)).FirstOrDefault();

Upvotes: 2

Related Questions