Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取枚举标志所有位的最佳方法?_C#_Enums - Fatal编程技术网

C# 获取枚举标志所有位的最佳方法?

C# 获取枚举标志所有位的最佳方法?,c#,enums,C#,Enums,我有一个带有Flags属性的枚举 我的问题是,我想得到所有选项的整数位掩码,而不需要自己手动组合所有位。 我想这样做是为了与其他一些int字段进行比较,并且我想保护将来的开发人员在enum中添加更多位选项的情况 另一件事是我的枚举标志中的位都是手动分配的,所以我不能简单地获取下一个值并减去1。看看我的项目,它做了一些坏事,允许在约束到枚举和委托的通用方法上构建好的功能 在这种情况下,我想您应该调用Flags.GetUsedBits() 如果你不介意使用一个额外的(非常小的)库,我想在处理旗帜时,

我有一个带有Flags属性的枚举

我的问题是,我想得到所有选项的整数位掩码,而不需要自己手动组合所有位。 我想这样做是为了与其他一些int字段进行比较,并且我想保护将来的开发人员在enum中添加更多位选项的情况

另一件事是我的枚举标志中的位都是手动分配的,所以我不能简单地获取下一个值并减去1。

看看我的项目,它做了一些坏事,允许在约束到枚举和委托的通用方法上构建好的功能

在这种情况下,我想您应该调用
Flags.GetUsedBits()

如果你不介意使用一个额外的(非常小的)库,我想在处理旗帜时,无约束的旋律会让生活变得更好。如果您有任何功能请求,我很乐意看一看:)

//使用ulong处理所有可能的底层类型而不会出错
var allFlags=Enum.GetValues(typeof(YourEnumType))
.Cast()
.Aggregate((YourEnumType)0,(a,x)=>a | x,a=>(ulong)a);

这里有一个方法,使用Jon Skeet和Marc Gravell所写的文章中的想法:

void Main()
{
    Console.WriteLine(CombineAllFlags<MyEnum>()); // Prints "Foo, Bar, Baz"
}

[Flags]
public enum MyEnum
{
    Foo = 1,
    Bar = 2,
    Baz = 4
}

public static TEnum CombineAllFlags<TEnum>()
{
    TEnum[] values = (TEnum[])Enum.GetValues(typeof(TEnum));
    TEnum tmp = default(TEnum);
    foreach (TEnum v in values)
    {
        tmp = EnumHelper<TEnum>.Or(tmp, v);
    }
    return tmp;
}

static class EnumHelper<T>
{
    private static Func<T, T, T> _orOperator = MakeOrOperator();

    private static Func<T, T, T> MakeOrOperator()
    {
        Type underlyingType = Enum.GetUnderlyingType(typeof(T));
        ParameterExpression xParam = Expression.Parameter(typeof(T), "x");
        ParameterExpression yParam = Expression.Parameter(typeof(T), "y");
        var expr =
            Expression.Lambda<Func<T, T, T>>(
                Expression.Convert(
                    Expression.Or(
                        Expression.Convert(xParam, underlyingType),
                        Expression.Convert(yParam, underlyingType)),
                    typeof(T)),
                xParam,
                yParam);
        return expr.Compile();
    }

    public static T Or(T x, T y)
    {
        return _orOperator(x, y);
    }   
}
void Main()
{
Console.WriteLine(CombineAllFlags());//打印“Foo,Bar,Baz”
}
[旗帜]
公共枚举髓鞘
{
Foo=1,
巴=2,
Baz=4
}
公共静态TEnum CombineAllFlags()
{
TEnum[]值=(TEnum[])Enum.GetValues(typeof(TEnum));
TEnum tmp=默认值(TEnum);
foreach(价值为十纳姆v)
{
tmp=EnumHelper.Or(tmp,v);
}
返回tmp;
}
静态类枚举帮助器
{
私有静态Func_orOperator=MakeOrOperator();
私有静态Func MakeOrOperator()
{
Type underyingtype=Enum.getunderyingtype(typeof(T));
ParameterExpression xParam=表达式参数(typeof(T),“x”);
ParameterExpression yParam=表达式。参数(typeof(T),“y”);
变量表达式=
Lambda(
表达式。转换(
表达。或(
Expression.Convert(xParam,underyingtype),
Expression.Convert(yParam,underyingtype)),
类型(T)),
xParam,
伊帕兰);
返回expr.Compile();
}
公共静态T或(T x,T y)
{
返回运算器(x,y);
}   
}

这段代码动态创建一个委托,该委托将枚举值与OR运算符组合在一起

如果我正确理解了您的要求,这应该适用于您:

Enum.GetValues(typeof(Enum)).Cast<int>().Sum();

有点粗糙,但像这样的东西

[Flags]
enum SomeFlags
{
    Flag1 = 1,
    Flag2 = 2,
    Flag3 = 4,
    Flag4 = 16,
    Flag5 = 32,
    Flag6 = 64
}

static void Main(string[] args)
{
    SomeFlags flags = 0;

    SomeFlags[] values = (SomeFlags[])Enum.GetValues(typeof(SomeFlags));
    Array.ForEach<SomeFlags>(values, delegate(SomeFlags v) { flags |= v; });

    int bitMask = Convert.ToInt32(flags);
}
[标志]
枚举某些标志
{
Flag1=1,
Flag2=2,
Flag3=4,
Flag4=16,
Flag5=32,
Flag6=64
}
静态void Main(字符串[]参数)
{
SomeFlags=0;
SomeFlags[]value=(SomeFlags[])Enum.GetValues(typeof(SomeFlags));
ForEach(值,委托(SomeFlags v){flags}=v;});
int bitMask=Convert.ToInt32(标志);
}

除非有人本机提出了一些建议,否则我会接受这个答案。@Winforms:哦,当然,您可以在自己的代码中不受约束地执行我所做的任何操作-除了使用泛型约束将类型参数约束为枚举(或委托)之外。这就是邪恶的黑客行为…只有在定义的类型中没有重复的情况下才有效,这通常发生在同义词或预合成的公共组合中。这绝对是最干净的解决方案,而且您可以只获取返回的数组,并执行任何其他计算,比如ORing而不是求和。很好,但它只有在基础类型为int时才起作用(否则转换失败)。我建议的解决方案更为通用(但在这种情况下,可能有些过分了……)@LukeH我同意这些都是经常创建的。但OP不会要求对所有枚举值求和。他会知道那里有重复的组合标志,希望他会提到一些值不应该包含在总和中。这是我的想法。如果你只想添加某些值,你不会要求添加所有值。我只是认为这些都是有效的问题,但不在OP提出的问题范围内。如果他提到了其中的一些情况,我认为反对票和评论会更加相关。但他问了一个具体的问题,我给出了一个具体的答案。我不认为我们需要让答案比问题更难。我不能+1这个,因为它与我在“添加答案”消息出现时键入的内容非常接近。它在长枚举上确实失败了,所以也许可以将强制转换为强制转换?@Jon:Fixed。聚合值现在被类型化为
ulong
,因此它可以处理所有可能的底层类型。(我将其强制转换为
YourEnumType
,因为OP要求整数位掩码。)
[Flags]
public enum Values
{
    Value_1 = 1,
    Value_2 = 2,
    Value_3 = 4,
    Value_4 = 8,
    Value_5 = 16,
    Value_6 = 32,
    Value_7 = 64,
    Value_8 = 128,
    Value_9 = 256
}

static void Main(string[] args)
{
    Values values = (Values)Enum.GetValues(typeof(Values)).Cast<int>().Sum();
}
[Flags]
enum SomeFlags
{
    Flag1 = 1,
    Flag2 = 2,
    Flag3 = 4,
    Flag4 = 16,
    Flag5 = 32,
    Flag6 = 64
}

static void Main(string[] args)
{
    SomeFlags flags = 0;

    SomeFlags[] values = (SomeFlags[])Enum.GetValues(typeof(SomeFlags));
    Array.ForEach<SomeFlags>(values, delegate(SomeFlags v) { flags |= v; });

    int bitMask = Convert.ToInt32(flags);
}