Как передать несколько значений перечисления в C#?



иногда при чтении чужого кода C# я вижу метод, который будет принимать несколько значений перечисления в одном параметре. Я всегда думал, что это было здорово, но никогда не заглядывал в нее.



Ну, теперь я думаю, что у меня может быть потребность в этом, но не знаю, как




  1. установите подпись метода, чтобы принять это

  2. работа со значениями в методе

  3. определить перечислимый


для достижения такого рода вещь.




В моей конкретной ситуации, я хотел бы использовать систему.День недели, который определяется как:

[Serializable]
[ComVisible(true)]
public enum DayOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6
}


Я хочу иметь возможность передать один или несколько значений DayOfWeek в мой метод. Смогу ли я использовать это конкретное перечисление, как это? Как мне сделать 3 вещи, перечисленные выше?

949   10  

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)
    {
        ...
    }
}

с помощью опубликованных ответов и этих:

  1. FlagsAttribute Class (посмотрите на сравнение использования и не использования атрибута [Flags])
  2. Перечисление Флагов Атрибут

Я чувствую, что понимаю это довольно хорошо.

спасибо.

Comments

    Ничего не найдено.