【问题标题】:Converting "weekstring" to enum将“weekstring”转换为枚举
【发布时间】:2016-12-19 13:33:45
【问题描述】:

我目前正在处理一些从 SQL 数据库中剥离出来的自动化作业。

每个作业作为'RunDays' 类型的string(nvarchar(7)) 列。

假设值为'1111111',即'SMTWTFS'(星期日、星期一、[...])。

我已经创建了这个枚举:

public enum RunDays : int
{
    Sunday = 0, 
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thrusday = 4, 
    Friday = 5, 
    Saturday = 6     

    //Maybe int is bad here cause Wednesday = 3 & Monday + Tuesday is also 3 -.-      
}

但是如何转换为那个,反之亦然?

到目前为止,这是我尝试过的:

if(row["RunDays"] != DBNull.Value)
{
   for(int i = 0; i < row["RunDays"].ToString().Length; i++)
   {
      if(int.Parse(row["RunDays"].ToString()[i].ToString()) == 1)
      {
          job.RunDays = job.RunDays | (RunDays)i;
      }                            
   }
}

遗憾的是,我得到的只是 'Sunday' 作为值。

我做错了什么/我错过了什么?

【问题讨论】:

标签: c# parsing enums data-conversion


【解决方案1】:

如果你想要多个枚举值,你需要一个用[Flags] 属性标记的枚举,并给每个成员一个 2 的幂的值:

[Flags]
public enum RunDays : int
{
    Sunday = 1, 
    Monday = 2,
    Tuesday = 4,
    Wednesday = 8,
    Thrusday = 16, 
    Friday = 32, 
    Saturday = 64          
}

[Flags] 属性使枚举能够采用未明确声明的值(例如 5),并且 2 的幂确保每个组合都是唯一的。

【讨论】:

  • 你确定它以 0 开头吗?
  • 你可能是对的。我通常为 NoneNoDay 之类的值保留 0,但在这种情况下,它可能应该以 1 开头。编辑我的答案。
  • @FelixD.还请注意,在您的循环中,您需要将 (RunDays)i 替换为 (RunDays)(Math.Pow(2, i))
【解决方案2】:

以下枚举可以满足你的需要:

[Flags]
public enum RunDays : int
{
   Sunday = 1, 
   Monday = 2,
   Tuesday = 4,
   Wednesday = 8,
   Thrusday = 16, 
   Friday = 32, 
   Saturday = 64     
}

注意,枚举具有属性 [Flags],表明枚举可以被视为位字段(一组标志)。此外,您必须以 2 的幂定义每个常数。 此枚举可以具有 1-128 范围内的值,描述所有可能性。 要使用枚举,您只需将整数值转换为您的枚举

RunDays days = (RunDays)14;

这将返回枚举:星期一、星期二、星期三。

PS。 0 值的星期日不是正确的值,因为在这种情况下,星期日的数字表示为 0,即默认整数值。因此,它可能会导致意想不到的结果。通常建议对 0 值使用 None 或 Unknown 标签(如果你真的需要它)。

【讨论】:

    【解决方案3】:

    正如其他人已经说过的那样,您需要在enum 上使用[Flags] 属性并使值的幂为2,以便Monday+Tuesday!=Wednesday。使用 C# 7 的新 binary literals 功能使这变得特别方便:

    [Flags]
    enum RunDays
    {
        None    =       0b00000000,
        Sunday =        0b00000010,
        Monday =        0b00000100,
        Tuesday =       0b00001000,
        Wednesday =     0b00010000,
        Thursday =      0b00100000,
        Friday =        0b01000000,
        Saturday =      0b10000000,
    }
    

    由于您的索引不再与enum 值相同,因此您不能再进行强制转换;转换为数组是一种方法:

        static readonly List<RunDays> s_runDays = Enum.GetValues(typeof(RunDays)).Cast<RunDays>().ToList();
        static RunDays Parse(string s)
        {
            if (String.IsNullOrWhiteSpace(s)) throw new ArgumentNullException(nameof(s));
            if (s.Length != 7) throw new ArgumentOutOfRangeException(nameof(s));
    
            var retval = RunDays.None;
            for (int i = 0; i < s.Length; i++)
                if (Int32.TryParse(s[i].ToString(), out var result) && (result > 0))
                    retval |= s_runDays[i+1];
            return retval;      
        }
    

    这样,您现在可以获得所需的结果:

        static void Main(string[] args)
        {
            var monday = Parse("0100000"); // Monday
            var weekends = Parse("1000001");    // Sunday | Saturday
            var weekdays = Parse("0111110"); // Monday | Tuesday | Wednesday | Thursday | Friday
        }
    

    【讨论】:

    • 这是一个非常巧妙的解决方案。非常感谢!
    猜你喜欢
    • 2020-08-21
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多