8

3 つの bool プロパティを持つレガシー クラスをフラグ列挙型に変換する必要があります。

私は、それらの特性の少なくとも 1 つが真であることを知っています。

[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;
            }
        }
    }
}

さらに多くのプロパティとフラグを設定するケースに遭遇する可能性があることを考慮して、これを行うためのよりエレガントまたは簡潔な方法はありますか?

4

4 に答える 4

13

このようなものはどうですか?

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;
        }
    }
}
于 2013-10-29T11:06:05.453 に答える
10

コードで分岐を使用する代わりに、コードを簡素化するために小さな関数と組み合わせてビット単位の算術演算を行うことができます。

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 を計算します。

于 2013-10-29T11:06:23.187 に答える
2

これはどう?

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);
}
于 2013-10-29T11:08:14.203 に答える
1

これにはビット演算を使用する必要がありますか? ここでは、非ビット単位のアプローチが機能すると思われます。

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-10-29T11:06:00.720 に答える