如何在C#中传递多个枚举值?

Ron*_*rby 111 c# enums

有时在阅读其他人的C#代码时,我看到一个方法可以在一个参数中接受多个枚举值.我一直以为它有点整洁,但从未接受过它.

好吧,现在我想我可能需要它,但不知道该怎么做

  1. 设置方法签名以接受此
  2. 使用方法中的值
  3. 定义枚举

实现这种事情.


在我的特殊情况下,我想使用System.DayOfWeek,它被定义为:

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

我希望能够将一个或多个DayOfWeek值传递给我的方法.我可以使用这个特殊的枚举吗?我如何做上面列出的3件事?

Ree*_*sey 173

当你定义枚举时,只需用[Flags]来定义它,将值设置为2的幂,它就会以这种方式工作.

除了将多个值传递给函数之外,没有其他任何更改.

例如:

[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);
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅MSDN关于枚举类型的文档.


编辑以回应问题的添加.

除非您想要将其作为数组/集合/ params数组传递,否则您将无法按原样使用该枚举.那会让你传递多个值.flags语法要求将Enum指定为标志(或者以未设计的方式对语言进行标准化).

  • 我想如果你想让它工作,那么值需要被定义为2的幂,每个值的一个位.发生的情况是您传入参数中值的按位OR,您可以使用按位AND运算进行检查.如果你不注意定义值,例如1,2,4,8等,你就会遇到问题. (9认同)
  • 哇...你快点了! (4认同)
  • 没问题......我仍然喜欢使用十六进制作为那样的标志值,对我来说似乎更清楚,但每个都是他自己的. (2认同)

Til*_*ito 76

我认为更优雅的解决方案是使用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);
    }
Run Code Online (Sandbox Code Playgroud)


Jac*_*cob 23

我是里德的第二个回答.但是,在创建枚举时,必须为每个枚举成员指定值,以使其成为一种位字段.例如:

[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.
}
Run Code Online (Sandbox Code Playgroud)

  • 为了清晰和可维护性,我会将"全部"枚举写为"星期日|星期一|星期二|星期三|星期四|星期五|星期六"...并对"工作日"和"周末"使用类似的表示法. (3认同)
  • 不是"可能想要"......你必须.按位比较需要它.保留未指定的值将不起作用. (2认同)

Rob*_*son 11

在我的特殊情况下,我想使用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 );
Run Code Online (Sandbox Code Playgroud)

否则,您可以[Flags]按照许多其他响应者的概述创建自己的枚举,并使用按位比较.

  • 我不知道为什么我没想到params.这对于使用非位域的枚举非常有用. (2认同)

Tet*_*ron 9

[Flags]
public enum DaysOfWeek
{
  Mon = 1,
  Tue = 2,
  Wed = 4,
  Thur = 8,
  Fri = 16,
  Sat = 32,
  Sun = 64
}
Run Code Online (Sandbox Code Playgroud)

您必须指定数字,并像这样递增它们,因为它以按位方式存储值.

然后只需定义你的方法来获取这个枚举

public void DoSomething(DaysOfWeek day)
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

并称之为做类似的事情

DoSomething(DaysOfWeek.Mon | DaysOfWeek.Tue) // Both Monday and Tuesday
Run Code Online (Sandbox Code Playgroud)

要检查是否包含其中一个枚举值,请使用按位操作检查它们

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
  }
}
Run Code Online (Sandbox Code Playgroud)


Ron*_*ony 6

[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
}
Run Code Online (Sandbox Code Playgroud)

以这种格式调用方法

MethodName(DaysOfWeek.Tuesday | DaysOfWeek.Thursday);
Run Code Online (Sandbox Code Playgroud)

实现 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();
}
Run Code Online (Sandbox Code Playgroud)


sta*_*son 5

使用 [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
}
Run Code Online (Sandbox Code Playgroud)

当您有接受 DayOfWeek 枚举的方法时,请使用按位或运算符 (|) 一起使用多个成员。例如:

MyMethod(DayOfWeek.Sunday|DayOfWeek.Tuesday|DayOfWeek.Friday)
Run Code Online (Sandbox Code Playgroud)

要检查参数是否包含特定成员,请对要检查的成员使用按位与运算符 (&)。

if(arg & DayOfWeek.Sunday == DayOfWeek.Sunday)
Console.WriteLine("Contains Sunday");
Run Code Online (Sandbox Code Playgroud)