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

有时在阅读别人的 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
}

我希望能够向我的方法传递一个或多个 DayOfWeek 值。我可以按原样使用这个枚举吗?我如何做上面列出的3件事情?

107086 次浏览

当您定义枚举时,只需将它与[ 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);
}

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


根据问题的补充进行编辑。

您将无法按原样使用该枚举,除非您希望将其作为数组/集合/参数数组传递。这将允许您传递多个值。标志语法要求将 Enum 指定为标志(或者以不符合其设计的方式破坏语言)。

这种性质的东西应该表明你在寻找什么:

[Flags]
public enum SomeName
{
Name1,
Name2
}


public class SomeClass()
{
public void SomeMethod(SomeName enumInput)
{
...
}
}

我同意 Reed 的回答。但是,在创建枚举时,必须为每个枚举成员指定值,以便它生成一种位字段。例如:

[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.
}
[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.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();
}
[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 ]属性标记枚举。还要确保所有的值都是相互排斥的(两个值加起来不等于另一个) ,比如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");

里德科普塞是正确的,我会添加到原来的职位,如果我可以,但我不能,所以我将不得不回复代替。

对任何旧的枚举使用[标志]都是危险的。我相信在使用标志时,您必须显式地将枚举值更改为2的幂,以避免值中的冲突。看看 FlagsAttribute 和 Enum 的准则

在这些答案的帮助下:

  1. FlagsAttribute Class (查看使用和不使用[ Flags ]属性的比较)
  2. 枚举标志属性

我觉得我很了解。

谢谢。

在我这种特殊情况下,我会的 喜欢使用系统

您不能使用系统。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]枚举,如许多其他响应者所概述的那样,并使用按位比较。

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