Как передать несколько значений перечисления в C#?
иногда при чтении чужого кода C# я вижу метод, который будет принимать несколько значений перечисления в одном параметре. Я всегда думал, что это было здорово, но никогда не заглядывал в нее.
Ну, теперь я думаю, что у меня может быть потребность в этом, но не знаю, как
- установите подпись метода, чтобы принять это
- работа со значениями в методе
- определить перечислимый
для достижения такого рода вещь.
В моей конкретной ситуации, я хотел бы использовать систему.День недели, который определяется как:
[Serializable]
[ComVisible(true)]
public enum DayOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6
}
Я хочу иметь возможность передать один или несколько значений DayOfWeek в мой метод. Смогу ли я использовать это конкретное перечисление, как это? Как мне сделать 3 вещи, перечисленные выше?
10 ответов:
когда вы определяете перечисление, просто атрибутируйте его с помощью [Flags], установите значения в степени двух, и он будет работать таким образом.
ничего не изменится, кроме передачи нескольких значений в функцию.
например:
[Flags] enum DaysOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, Wednesday = 8, Thursday = 16, Friday = 32, Saturday = 64 } public void RunOnDays(DaysOfWeek days) { bool isTuesdaySet = (days & DaysOfWeek.Tuesday) == DaysOfWeek.Tuesday; if (isTuesdaySet) //... // Do your work here.. } public void CallMethodWithTuesdayAndThursday() { this.RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday); }дополнительные сведения см. В разделе документация MSDN по типам перечисления.
редактировать в ответ на дополнения к вопросу.
вы не сможете использовать это перечисление как, если вы хотел сделать что-то вроде передать его в виде массива/коллекции/массива params. Это позволит вам передать несколько значений. Синтаксис flags требует, чтобы перечисление указывалось как флаги (или убирать язык таким образом, чтобы он не был разработан).
Я думаю, что более элегантным решением является использование HasFlag ():
[Flags] public enum DaysOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, Wednesday = 8, Thursday = 16, Friday = 32, Saturday = 64 } public void RunOnDays(DaysOfWeek days) { bool isTuesdaySet = days.HasFlag(DaysOfWeek.Tuesday); if (isTuesdaySet) { //... } } public void CallMethodWithTuesdayAndThursday() { RunOnDays(DaysOfWeek.Tuesday | DaysOfWeek.Thursday); }
Я поддерживаю ответ Рида. Однако при создании перечисления необходимо указать значения для каждого элемента перечисления, чтобы он создавал своего рода битовое поле. Например:
[Flags] public enum DaysOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, Wednesday = 8, Thursday = 16, Friday = 32, Saturday = 64, None = 0, All = Weekdays | Weekend, Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday, Weekend = Sunday | Saturday, // etc. }
в моей конкретной ситуации, я бы нравится пользоваться системой.День недели
вы не можете использовать систему.DayOfWeek как
[Flags]перечисления, потому что у вас нет контроля над ним. Если вы хотите иметь метод, который принимает несколькоDayOfWeekтогда вам придется использоватьparamsключевое словоvoid SetDays(params DayOfWeek[] daysToSet) { if (daysToSet == null || !daysToSet.Any()) throw new ArgumentNullException("daysToSet"); foreach (DayOfWeek day in daysToSet) { // if( day == DayOfWeek.Monday ) etc .... } } SetDays( DayOfWeek.Monday, DayOfWeek.Sunday );в противном случае вы можете создать свой собственный
[Flags]перечисление, как указано многими другими респондентами и использовать побитовые сравнения.
[Flags] public enum DaysOfWeek { Mon = 1, Tue = 2, Wed = 4, Thur = 8, Fri = 16, Sat = 32, Sun = 64 }вы должны указать числа, и увеличить их, как это, потому что он хранит значения в побитовой форме.
тогда просто определите свой метод, чтобы взять это перечисление
public void DoSomething(DaysOfWeek day) { ... }и назвать это сделать что-то вроде
DoSomething(DaysOfWeek.Mon | DaysOfWeek.Tue) // Both Monday and Tuesdayчтобы проверить, было ли включено одно из значений перечисления, проверьте их с помощью побитовых операций, таких как
public void DoSomething(DaysOfWeek day) { if ((day & DaysOfWeek.Mon) == DaysOfWeek.Mon) // Does a bitwise and then compares it to Mondays enum value { // Monday was passed in } }
[Flags] public enum DaysOfWeek{ Sunday = 1 << 0, Monday = 1 << 1, Tuesday = 1 << 2, Wednesday = 1 << 3, Thursday = 1 << 4, Friday = 1 << 5, Saturday = 1 << 6 }вызовите метод в этом формате
MethodName (DaysOfWeek.Вторник / Дни Недели.Четверг);
реализовать метод EnumToArray, чтобы получить параметры, переданные
private static void AddEntryToList(DaysOfWeek days, DaysOfWeek match, List<string> dayList, string entryText) { if ((days& match) != 0) { dayList.Add(entryText); } } internal static string[] EnumToArray(DaysOfWeek days) { List<string> verbList = new List<string>(); AddEntryToList(days, HttpVerbs.Sunday, dayList, "Sunday"); AddEntryToList(days, HttpVerbs.Monday , dayList, "Monday "); ... return dayList.ToArray(); }
отметьте свое перечисление атрибутом [Flags]. Также убедитесь, что все ваши значения являются взаимоисключающими (два значения не могут быть равны друг другу), как 1,2,4,8,16,32,64 в вашем случае
[Flags] public enum DayOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, Wednesday = 8, Thursday = 16, Friday = 32, Saturday = 64 }Если у вас есть метод, который принимает перечисление DayOfWeek, используйте побитовый оператор or (|) для совместного использования нескольких элементов. Например:
MyMethod(DayOfWeek.Sunday|DayOfWeek.Tuesday|DayOfWeek.Friday)чтобы проверить, содержит ли параметр определенный элемент, используйте побитовое и оператор (&) с членом вы проверяете наличие.
if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday) Console.WriteLine("Contains Sunday");
Рид Копси прав, и я бы добавил к исходному сообщению, если бы мог, но я не могу, поэтому мне придется ответить вместо этого.
его опасно просто использовать [флаги] на любом старом перечислении. Я считаю, что вы должны явно изменить значения перечисления на степени двух при использовании флагов, чтобы избежать столкновений в значениях. Смотрите рекомендации для FlagsAttribute и Enum.
что-то такого рода должно показать, что вы ищете:
[Flags] public enum SomeName { Name1, Name2 } public class SomeClass() { public void SomeMethod(SomeName enumInput) { ... } }
с помощью опубликованных ответов и этих:
- FlagsAttribute Class (посмотрите на сравнение использования и не использования атрибута [Flags])
- Перечисление Флагов Атрибут
Я чувствую, что понимаю это довольно хорошо.
спасибо.
Comments