【问题标题】:How do you pass multiple enum values in C#?如何在 C# 中传递多个枚举值?
【发布时间】:2010-11-05 00:44:27
【问题描述】:

有时在阅读其他人的 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 件事?

【问题讨论】:

  • 如下所述,您可以使用 Flags 枚举。您可能想查看The ins and outs of C# enums,其中包含有关使用标志枚举的更多信息。

标签: c# enums


【解决方案1】:

定义枚举时,只需使用 [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's documentation on Enumeration Types


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

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

【讨论】:

  • 我认为如果你想让它工作,值需要定义为 2 的幂,每个值一个位。发生的情况是您传入参数中值的按位或,您可以使用按位与运算进行检查。如果您不注意将值定义为例如 1、2、4、8 等,您将会遇到问题。
  • 仅设置 Flags 属性不会自动工作。我刚试过。
  • 你是对的,我删除了错误信息。也为他修复了 Reed 的代码。
  • @monoxide:我同时修复了它 - 抱歉覆盖您的编辑。
  • 没问题...我仍然更喜欢使用十六进制来表示这样的标志值,对我来说似乎更清楚,但每个人都有自己的。
【解决方案2】:

这种性质的东西应该显示您正在寻找的东西:

[Flags]
public enum SomeName
{
    Name1,
    Name2
}

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

【讨论】:

    【解决方案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.
    }
    

    【讨论】:

    • 如果您需要检查 DaysOfWeek 值,例如,如果您正在读取存储在数据库中的值,它将为您提供帮助。此外,它为其他程序员提供了更好的文档,因为一周中的某些天数从星期一而不是星期日开始。
    • 为了清晰和可维护性,我会将您的“所有”枚举写为“Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday”...并对“工作日”和'周末'。
    • 如果您想创建自己的枚举,这很好,但要回答您无法更改现有 DaysOfWeek 枚举的问题
    • 不是“可能想要”……你必须这样做。按位比较需要它。保留未指定的值将不起作用。
    【解决方案4】:
    [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();
    }
    

    【讨论】:

    • 不回答问题。 “在我的特殊情况下,我想使用 System.DayOfWeek”
    • 谢谢,罗伯特,但你真的不必在每个答案上都指出这一点。
    • @Ronnie - 有这么多几乎重复的答案实际上并没有回答问题,这几乎不是我的错。
    • @Rony - 枚举 ToString() 和 Enum.Parse() 将正确输出/解析 [Flags] 枚举(当然,只要您注意枚举版本)
    • @Robert - 我认为没有人责备你。让投票来说话吧。
    【解决方案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
      }
    }
    

    【讨论】:

    • 不回答问题。 “在我的特殊情况下,我想使用 System.DayOfWeek”
    • 但这正是我一直在寻找的。无论如何,谢谢。
    【解决方案6】:

    用 [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");
    

    【讨论】:

    • 不回答问题。 “在我的特殊情况下,我想使用 System.DayOfWeek”
    【解决方案7】:

    Reed Copsey 是正确的,如果可以的话,我会添加到原始帖子中,但我不能,所以我不得不回复。

    仅在任何旧枚举上使用 [Flags] 是很危险的。我相信您必须在使用标志时将枚举值显式更改为 2 的幂,以避免值冲突。请参阅guidelines for FlagsAttribute and Enum

    【讨论】:

      【解决方案8】:

      借助已发布的答案和这些:

      1. FlagsAttribute Class(看看使用和不使用[Flags]属性的对比)
      2. Enum Flags Attribute

      我觉得我理解得很好。

      谢谢。

      【讨论】:

        【解决方案9】:

        在我的特殊情况下,我会 喜欢使用 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] 枚举,如众多其他响应者所述,并使用按位比较。

        【讨论】:

        • 我不知道为什么我没有想到参数。这对于使用不是位域的枚举应该非常有用。
        【解决方案10】:

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

        【讨论】:

        • 如果你这样做,还有另一件重要的事情要知道:当你需要动态填充你的枚举时,它会增加更多的灵活性。例如:如果您使用复选框来定义您希望程序运行的日期,并且您会尝试按照上面的方式完成此操作,那么代码将不可读。因此,您可以这样做: ... DaysOfWeek days = new DaysOfWeek(); if (cbTuesday.Checked) days |= DaysOfWeek.Tuesday; if (cbWednesday.Checked) days |= DaysOfWeek.Wednesday; ...
        猜你喜欢
        • 1970-01-01
        • 2022-01-20
        • 1970-01-01
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-16
        • 2023-02-06
        相关资源
        最近更新 更多