【问题标题】:Convert some bool properties to a flags enum将一些布尔属性转换为标志枚举
【发布时间】:2013-10-29 10:55:37
【问题描述】:

我需要将具有 3 个布尔属性的遗留类转换为标志枚举。

我知道这些属性中至少有一个是正确的。

[Flags]
public enum FlagEnum
{
    EnumValue1 = 1,
    EnumValue2 = 2,
    EnumValue3 = 4
}

public class LegacyClass
{
    public bool PropA { get; set; }
    public bool PropB { get; set; }
    public bool PropC { get; set; }
}

public class DtoClass
{
    public FlagEnum FlagEnum { get; set; }

    public DtoClass(LegacyClass legacyClass)
    {
        if (!legacyClass.PropA && !legacyClass.PropB && !legacyClass.PropC)
        {
            throw new ArgumentException();
        }

        if (legacyClass.PropA)
        {
            FlagEnum = FlagEnum.EnumValue1;
        }
        if (legacyClass.PropB)
        {
            if (legacyClass.PropA)
            {
                FlagEnum = FlagEnum.EnumValue1|FlagEnum.EnumValue2;
            }
            else
            {
                FlagEnum = FlagEnum.EnumValue2;
            }
        }
        if (legacyClass.PropC)
        {
            if (legacyClass.PropA||legacyClass.PropB)
            {
                FlagEnum = FlagEnum | FlagEnum.EnumValue3;
            }
            else
            {
                FlagEnum = FlagEnum.EnumValue3;
            }
        }
    }
}

考虑到我可能会遇到需要设置更多属性和标志的情况,是否有更优雅或更简洁的方法?

【问题讨论】:

  • @BartoszKP FlagEnum = FlagEnum | FlagEnum.EnumValue3;
  • @BartoszKP 没问题! :)

标签: c# enums enum-flags


【解决方案1】:

这样的事情怎么样?

using System;

namespace ConsoleApplication1
{

    [Flags]
    public enum FlagEnum
    {
        EnumValue1 = 1,
        EnumValue2 = 2,
        EnumValue3 = 4
    }

    public static class LegacyClass
    {
        public static bool PropA { get; set; }
        public static bool PropB { get; set; }
        public static bool PropC { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            LegacyClass.PropB = true;
            FlagEnum result = LegacyClass.PropA ? FlagEnum.EnumValue1 : 0;
            result |= LegacyClass.PropB ? FlagEnum.EnumValue2 : 0;
            result |= LegacyClass.PropC ? FlagEnum.EnumValue3 : 0;
        }
    }
}

【讨论】:

    【解决方案2】:

    除了在代码中使用分支,您还可以结合一个小函数进行按位算术以简化代码:

    T GetFlag<T>(Boolean value, T flag) {
      return value ? flag : default(T);
    }
    

    要计算枚举值,您可以使用以下表达式:

    var flagEnum = GetFlag(legacyClass.PropA, FlagEnum.EnumValue1)
      | GetFlag(legacyClass.PropB, FlagEnum.EnumValue2)
      | GetFlag(legacyClass.PropC, FlagEnum.EnumValue3);
    

    请注意,如果未设置任何标志,您的代码将抛出 ArgumentException。此代码将改为计算 default(FlagEnum),在本例中为 0。

    【讨论】:

    • 不会 default(T) 总是返回枚举中的第一个值吗?如果是这样,那么即使传入的布尔值是假的,也会始终设置该标志。
    • T 是一个枚举时default(T) 返回(T) 0,即使枚举的第一个值不是0。
    • 哦,不知道。谢谢。
    【解决方案3】:

    这个怎么样?

    public DtoClass(LegacyClass legacyClass)
    {
        if (!legacyClass.PropA && !legacyClass.PropB && !legacyClass.PropC)
        {
            throw new ArgumentException();
        }
        FlagEnum =  ((legacyClass.PropA) ? FlagEnum.EnumValue1 : FlagEnum)
            | ((legacyClass.PropB) ? FlagEnum.EnumValue2 : FlagEnum)
            | ((legacyClass.PropC) ? FlagEnum.EnumValue3 : FlagEnum);
    }
    

    【讨论】:

      【解决方案4】:

      您必须为此使用按位运算吗?我怀疑非按位方法可以在这里工作:

      FlagEnum = (FlagEnum)(1 * (ToInt(legacyClass.PropA)) 
                  + 2 * (ToInt(legacyClass.PropB)) 
                  + 4 * (ToInt(legacyClass.PropC)));
      

      假设我们有一个函数

      int ToInt(bool b) { return b ? 1 : 0; }
      

      如果枚举遗留类中的布尔值,则可以更简洁地完成 - 然后我们可以使用 Math.Pow(n, 2) 应用公式。但这是一种设计选择。

      【讨论】:

        猜你喜欢
        • 2013-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多