Как вы передаете несколько значений enum в С#?
Иногда при чтении кода других С# я вижу метод, который принимает несколько значений enum в одном параметре. Я всегда думал, что это было довольно аккуратно, но никогда не смотрел на него.
Ну, теперь я думаю, что мне может понадобиться это, но не знаю, как
- настроить подпись метода для принятия этого
- работать со значениями в методе
- определить перечисление
для достижения такого рода вещей.
В моей конкретной ситуации я хотел бы использовать System.DayOfWeek, который определяется как:
[Serializable]
[ComVisible(true)]
public enum DayOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6
}
Я хочу иметь возможность передать один или несколько значений DayOfWeek в мой метод. Смогу ли я использовать это перечисление как есть? Как я могу сделать 3 вещи, перечисленные выше?
Ответы
Ответ 1
Когда вы определяете перечисление, просто присвойте ему значение [Флаги], задайте значения в значениях двух, и он будет работать таким образом.
Ничего другого не происходит, кроме передачи нескольких значений в функцию.
Например:
[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 по типам перечислений.
Изменить в ответ на дополнения к вопросу.
Вы не сможете использовать это перечисление как есть, если только вы не захотите сделать что-то вроде передачи его в виде массива array/collection/params. Это позволит вам передать несколько значений. Синтаксис флагов требует, чтобы Enum указывался в виде флагов (или для упрощения языка таким образом, чтобы он не был разработан).
Ответ 2
Я думаю, что более элегантным решением является использование 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);
}
Ответ 3
Второй ответ Рида. Однако при создании перечисления вы должны указать значения для каждого члена перечисления, чтобы он сделал своеобразное поле бит. Например:
[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.
}
Ответ 4
В моей конкретной ситуации я бы как использовать System.DayOfWeek
Вы не можете использовать System.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]
, как описано многочисленными другими респондентами, и использовать побитовые сравнения.
Ответ 5
[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
}
}
Ответ 6
Отметьте свой enum атрибутом [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, используйте поразрядный или оператор (|), чтобы использовать несколько членов вместе. Например:
MyMethod(DayOfWeek.Sunday|DayOfWeek.Tuesday|DayOfWeek.Friday)
Чтобы проверить, содержит ли параметр определенный элемент, используйте побитовый и оператор (&) с членом, который вы проверяете.
if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday)
Console.WriteLine("Contains Sunday");
Ответ 7
[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
}
вызов метода в этом формате
Имя метода (DaysOfWeek.Tuesday | DaysOfWeek.Thursday);
Внедрить метод 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();
}
Ответ 8
Рид Копси прав, и я бы добавил к исходному сообщению, если мог, но я не могу, поэтому мне придется ответить вместо этого.
Его опасно просто использовать [Флаги] для любого старого перечисления. Я полагаю, что вы должны явно изменять значения перечисления до двух значений при использовании флагов, чтобы избежать столкновений в значениях. См. рекомендации для FlagsAttribute и Enum.
Ответ 9
Что-то в этом роде должно показать, что вы ищете:
[Flags]
public enum SomeName
{
Name1,
Name2
}
public class SomeClass()
{
public void SomeMethod(SomeName enumInput)
{
...
}
}
Ответ 10
С помощью опубликованных ответов и этих вопросов:
Я чувствую, что понимаю это довольно хорошо.
Спасибо.