16

与えられたenum

[Flags]
public enum mytest
{
    a = 1,
    b = 2,
    c = 4
}

すべての値を 1 つの変数で表すには、次の 2 つの方法があります。

    var OR1 = (mytest)Enum.GetNames(typeof(mytest)).Sum(a => (int)Enum.Parse(typeof(mytest), a));
    var OR2 = (mytest)(typeof(mytest).GetEnumValues() as mytest[]).Sum(a => (int)a);

さて、どちらも機能しますが、もっときちんとした方法はありますか? おそらく私が見逃している.NETメソッドですか?

編集:明確にするために、関数を動的にする必要があります-すべての値を指定して計算したくありませんenum

4

6 に答える 6

20

メンバーを持つことが理にかなっている場合は、All直接提供してください。

[Flags]
public enum mytest
{
    a = 1,
    b = 2,
    c = 4,
    All = 7
}

ただし、これらを記述するより慣用的な方法は次のようになります。

[Flags]
public enum MyTest
{
    A = 1,
    B = 1 << 0x01,
    C = 1 << 0x02,
    All = A | B | C
}

これは、列挙値の論理的な進行を示しており、このAll場合、別のメンバーを簡単に追加できます。

于 2013-03-08T16:08:58.413 に答える
14

Enumerable.Aggregate()ビットごとに使用するか、それらを一緒に使用します。とは対照的に、複数のセットビットを表す列挙値がある場合でも、これは機能しSum()ます。

var myTestValues = (MyTest[]) typeof(MyTest).GetEnumValues();
var sum = myTestValues.Aggregate((a, b) => a | b);
sum.Dump();

ジェネリック型を列挙型に制限することも、プリミティブ型が互いにサブタイプの関係を持たないこともできないため、これをジェネリックにするのは少し難しいです。私が思いつくことができる最高のものは、基になる型がintほとんどの場合十分であるはずであると仮定しています:

TEnum AllEnums<TEnum>() 
{
    var values = typeof(TEnum).GetEnumValues().Cast<int>();
    return (TEnum) (object) values.Aggregate((a,b) => a|b);
}
于 2013-03-08T16:10:38.557 に答える
6

ジェネリック メソッドの場合は、Linq のEnumerable.Aggregate拡張メソッドを使用します。

var flags = Enum.GetValues(typeof(mytest))
                .Cast<int>()
                .Aggregate(0, (s, f) => s | f);

またはラッパーメソッドで

TEnum GetAll<TEnum>() where TEnum : struct
{
    return (TEnum) (object)
            Enum.GetValues(typeof(TEnum))
                .Cast<int>()
                .Aggregate(0, (s, f) => s | f);
}

このダブル キャスト トリックの完全なクレジットは @millimoose にあります

于 2013-03-08T16:08:34.777 に答える
1

列挙型のすべてのビットが設定されていることを確認する最も簡単な方法は、すべてのビットを設定するだけです。

mytest allValues = (mytest)int.MaxValue;

これは、列挙型に対応しないビットの設定に問題がないことを前提としていますが、それはおそらく真実です。これを任意の列挙値とAND演算すると、それが実現します。これが最終目標である可能性があります。

于 2013-03-08T16:18:39.730 に答える
1

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

var all = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last() * 2 - 1;

基本的

all = max*2-1

これは、すべての値が 1 から最大値まで存在する場合にのみ機能します。

1,2,4...32,64...

于 2013-03-08T16:25:57.810 に答える
0

根底にある型キャストの問題を考えると、一見したほど簡単ではありません。

static public TEnum GetAllFlags<TEnum>() where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        unchecked
        {
            if (!typeof(TEnum).IsEnum)
                throw new InvalidOperationException("Can't get flags from non Enum");
            object val = null;
            switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(TEnum))))
            {
                case TypeCode.Byte:
                case TypeCode.SByte:
                    val = Enum.GetValues(typeof(TEnum))
                                .Cast<Byte>()
                                .Aggregate(default(Byte), ( s, f) => (byte)(s | f));
                    break;
                case TypeCode.Int16:
                case TypeCode.UInt16:
                    val = Enum.GetValues(typeof(TEnum))
                                .Cast<UInt16>()
                                .Aggregate(default(UInt16), ( s, f) => (UInt16)(s | f));
                    break;
                case TypeCode.Int32:
                case TypeCode.UInt32:
                    val = Enum.GetValues(typeof(TEnum))
                                .Cast<UInt32>()
                                .Aggregate(default(UInt32), ( s, f) => (UInt32)(s | f));
                    break;
                case TypeCode.Int64:
                case TypeCode.UInt64:
                    val = Enum.GetValues(typeof(TEnum))
                                .Cast<UInt64>()
                                .Aggregate(default(UInt64), ( s, f) => (UInt64)(s | f));
                    break;
                default :
                    throw new InvalidOperationException("unhandled enum underlying type");

            }
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }
    }

この種のコンバージョンの詳細については、こちらをご覧ください

于 2013-12-21T00:00:37.407 に答える