How to perform LINQ query over Enum?
Solution 1
Well if you're going to hard code the items that should be in the list anyway, why not just do this:
public static List<Activity.StatusEnum> StatusList()
{
return new List<Activity.StatusEnum>
{
Activity.StatusEnum.Open,
Activity.StatusEnum.Rejected,
Activity.StatusEnum.Accepted,
Activity.StatusEnum.Started
};
}
You could also dispose of the List<T>
and just return the array itself. As long as you know these are the items you want, then there's no need for Linq.
Solution 2
return Enum.GetValues(typeof(Activity.StatusEnum)).Cast<Activity.StatusEnum>().Where((n, x) => x < 4);
If you want to be able to change the list of items, just add them into a List<Activity.StatusEnum>
and use Contains
:
var listValid = new List<Activity.StatusEnum>() { Activity.StatusEnum.Open, Activity.StatusEnum.Rejected, Activity.StatusEnum.Accepted, Activity.StatusEnum.Started };
return Enum.GetValues(typeof(Activity.StatusEnum)).Cast<Activity.StatusEnum>().Where(n => listValid.Contains(n));
Solution 3
Steps:
- Get the
enum
values and cast the results to the type of theenum
- Sort the
enum
values by their integer values (otherwise they sort naturally by unsigned magnitude) - Take the first 4
Code:
return Enum.GetValues(typeof(Activity.StatusEnum))
.Cast<Activity.StatusEnum>()
.OrderBy(se =>(int)se)
.Take(4);
Output:
Open Rejected Accepted Started
Solution 4
First, if possible, I'd make your enum values powers of 2, so they could be OR'd together.
public enum StatusEnum
{
Open = 1,
Rejected = 2,
Accepted = 4,
Started = 8,
Completed = 16,
Cancelled = 32,
Assigned = 64
}
Then you could do something like this:
public static List<Activity.StatusEnum> StatusList()
{
var statusesToShow = Activity.StatusEnum.Open | Activity.StatusEnum.Rejected | Activity.StatusEnum.Accepted | Activity.StatusEnum.Started;
return Enum
.GetValues(typeof(Activity.StatusEnum))
.Cast<Activity.StatusEnum>()
.Where(x => (x & statusesToShow) == x)
.ToList();
}
EDIT: In light of the fact that you can't change the enum values, I'd just recommend you use something like:
public static List<Activity.StatusEnum> StatusList()
{
return new List<Activity.StatusEnum> {
Activity.StatusEnum.Open,
Activity.StatusEnum.Rejected,
Activity.StatusEnum.Accepted,
Activity.StatusEnum.Started
};
}
Solution 5
". . . only show the first 4 statuses and ignore the rest."
To get the first n
elements of an IEnumerable<T>
, use the Take
method:
return Enum.GetValues(typeof(Activity.StatusEnum))
.Cast<Activity.StatusEnum>()
.Take(4)
.ToList();
Learner
Updated on March 22, 2020Comments
-
Learner about 4 years
Below is my
Enumerator List
:public enum StatusEnum { Open = 1, Rejected = 2, Accepted = 3, Started = 4, Completed = 5, Cancelled = 6, Assigned = 7 }
I need to bind this to a
Combobox
, but, only show a few specific statuses and ignore the rest.This is what I have so far:
public static List<Activity.StatusEnum> StatusList() { IEnumerable<Activity.StatusEnum> query = Enum.GetValues(typeof(Activity.StatusEnum)).Cast<Activity.StatusEnum>() .Where(x => x == Activity.StatusEnum.Open || x == Activity.StatusEnum.Rejected || x == Activity.StatusEnum.Accepted || x == Activity.StatusEnum.Started); return query.ToList(); }
However, I feel that the code is little messy and is not a correct approach to bind filtered
Enum
list to aCombobox
. Can anyone suggest a more robust way of doing this?Update
I might need to change the Order of selection. So I need a generic solution which doesn't only get the first X number of statuses.
-
Yinda Yin almost 11 yearsI was thinking along these lines, but the use of a magic number bothers me. Maybe compare to
(int)StatusEnum.Started
? -
It'sNotALie. almost 11 years@RobertHarvey He said 4, not to compare against Started. It bothers me too, but this does exactly what asked. Unlike the most upvoted answer, too.
-
Learner almost 11 yearsIt's a good solution for this scenario, but I might need to change the order in future. Like just show Open, Completed and Assigned.
-
Jeppe Stig Nielsen almost 11 yearsUpvoted, but he should either change the return type into the array type
Activity.StatusEnum[]
, like you suggest, or use collection initializer syntax on theList<>
(just remove the five charatersnew[]
and the parenthesis()
). It is crazy to allocate an array that is immediately discarded again (only theList<>
is kept)! -
Learner almost 11 yearsSorry for the confusion but, I need a solution without Take(4) as the order might change for other situations.
-
It'sNotALie. almost 11 years@RobertHarvey I'd prefer to make a
List
and useContains
tbh -
Learner almost 11 yearsVery sorry for the confusion about quoted text. Please see the update. But this will help me. +1
-
Learner almost 11 yearsThanks for the suggestion but I am using objects which I don't have control over. +1 for solution.
-
p.s.w.g almost 11 years@JeppeStigNielsen Thanks, I'd forgotten about collection initializers.
-
Chris Doggett almost 11 years@Learner: In that case, you don't need to use Enum.GetValues at all, and can just initialize a List<T> with the known enums, which would be much easier. I'd also recommend using an IEnumerable<T> instead of List<T>, unless the binding specifically requires a List<T>.
-
Learner almost 11 yearsMay I know the reason for recommending IEnumerable<T>?
-
Chris Doggett almost 11 yearsIn general, it's considered a best practice to prefer using interfaces over specific implementations. If your code that calls this expects an IEnumerable<T>, it doesn't matter if the function itself uses List<T>, HashSet<T>, T[] (array), or any other implementation. It would only care that there's a number of items it can iterate over. It would also prevent code that called it from calling .Add() on the List<T>. Basically, you just want to give users what they NEED access to, and nothing more. It's probably overkill for this, but it's just generally a good practice.
-
Learner almost 11 yearsBTW, I will wait for Android version of Milestone ;)
-
Piotr Kula over 10 yearsWhat the heck is
<=
I have not seen that before!? :) Is that meant to be lest or equal or some other linq function I have never seen before? -
Bronek over 7 years@ppumkin it's "less than or equal" operator :)
-
Piotr Kula over 7 yearsSo embarrassing:) noob at Linq 3 years ago. :D
-
John Bustos over 7 yearsRight, @ppumkin??? - I look at some of my old questions and LOVE to see how far I've come! - Got to absolutely love this community for how much they've helped!!!!
-
Piotr Kula over 7 yearsCompletely agreed. So many problems solved, some pages are boookmarked because I keep on forgetting, like complex Grouping with Linq :) But for sure, since Spolsky opened Stack Overflow, the quality of code increased by 66%, globally :)