C# 使用泛型的逐位或逐位枚举
可以按位或枚举。通常这是在枚举上完成的 例如C# 使用泛型的逐位或逐位枚举,c#,generics,enums,C#,Generics,Enums,可以按位或枚举。通常这是在枚举上完成的 例如var foo=MyEnum.ABC | MyEnum.XCN 我尝试创建一个方法,使用泛型将枚举数组转换为组合枚举 以下是我尝试过的: private T CombineFlags<T>(params T[] flags) where T : struct, IConvertible { return flags.Select(flag => flag).Aggregate((x, y) => x | y); } p
var foo=MyEnum.ABC | MyEnum.XCN
我尝试创建一个方法,使用泛型将枚举数组转换为组合枚举
以下是我尝试过的:
private T CombineFlags<T>(params T[] flags) where T : struct, IConvertible
{
return flags.Select(flag => flag).Aggregate((x, y) => x | y);
}
private T CombineFlags(参数T[]标志),其中T:struct,IConvertible
{
返回标志。选择(标志=>flag)。聚合((x,y)=>x | y);
}
但是,我无法将运算符“\”应用于t和t。强制转换似乎没有帮助struct,IConvertible
似乎是我能找到的最接近枚举的,但显然不够接近,无法使用“|”运算符。枚举也不是很有帮助
如何在通用枚举上执行此操作?(可能吗?无法对类型为
Enum
的类型应用泛型约束,也无法应用类型重载
运算符的约束,因此您所做的任何操作都无法完全保持静态类型
您可以做的是将枚举更改为其基础整数类型,进行聚合,然后将其回滚。问题是,动态确定基础类型并对该类型执行按位or操作(同样是由于缺少对具有重载|
运算符的类型的约束)时,您无法(轻松)解决这个问题。如果可以假定枚举的基础类型是int
(或任何较小的类型),则可以这样做,但如果枚举的基础类型是long
,则此代码将中断。还有一个事实,非枚举值可以用于T
,这些类型在传递给此方法时可能会正常工作,也可能不会正常工作
private static T CombineFlags<T>(params T[] flags) where T : struct, IConvertible
{
int n = flags.Select(flag => Convert.ToInt32(flag))
.Aggregate((x, y) => x | y);
return (T)(object)n;
}
private static T CombineFlags(参数T[]标志),其中T:struct,IConvertible
{
int n=flags.Select(flag=>Convert.ToInt32(flag))
.骨料((x,y)=>x | y);
返回(T)(对象)n;
}
无法对类型为枚举的类型应用泛型约束,也无法应用类型重载
运算符的约束,因此您所做的任何操作都无法完全保持静态类型
您可以做的是将枚举更改为其基础整数类型,进行聚合,然后将其回滚。问题是,动态确定基础类型并对该类型执行按位or操作(同样是由于缺少对具有重载|
运算符的类型的约束)时,您无法(轻松)解决这个问题。如果可以假定枚举的基础类型是int
(或任何较小的类型),则可以这样做,但如果枚举的基础类型是long
,则此代码将中断。还有一个事实,非枚举值可以用于T
,这些类型在传递给此方法时可能会正常工作,也可能不会正常工作
private static T CombineFlags<T>(params T[] flags) where T : struct, IConvertible
{
int n = flags.Select(flag => Convert.ToInt32(flag))
.Aggregate((x, y) => x | y);
return (T)(object)n;
}
private static T CombineFlags(参数T[]标志),其中T:struct,IConvertible
{
int n=flags.Select(flag=>Convert.ToInt32(flag))
.骨料((x,y)=>x | y);
返回(T)(对象)n;
}
您可以创建一个静态助手方法,为聚合生成所需的或函数。该函数在首次访问时生成,并缓存以供其他使用
这假定传递的类型将是枚举
public T CombineFlags<T>(params T[] flags)
where T : struct, IConvertible
{
return flags.Select(flag => flag).Aggregate(EnumHelper<T>.OrFunction);
}
private class EnumHelper<T>
where T : struct,IConvertible
{
static readonly Type typeofT = typeof(T);
static readonly Type underlyingType = Enum.GetUnderlyingType(typeofT);
static readonly ParameterExpression[] parameters =
{
Expression.Parameter(typeofT),
Expression.Parameter(typeofT)
};
static readonly Func<T, T, T> _orFunc = Expression.Lambda<Func<T, T, T>>(
Expression.Convert(Expression.Or(
Expression.Convert(parameters[0], underlyingType),
Expression.Convert(parameters[1], underlyingType)
), typeofT), parameters).Compile();
public static Func<T, T, T> OrFunction { get { return _orFunc; } }
}
public T组合标志(参数T[]标志)
其中T:struct,IConvertible
{
返回flags.Select(flag=>flag.Aggregate(EnumHelper.OrFunction);
}
私有类枚举帮助器
其中T:struct,IConvertible
{
静态只读类型typeofT=typeof(T);
静态只读类型underyingtype=Enum.getunderyingtype(typeofT);
静态只读参数expression[]参数=
{
表达式参数(typeofT),
Expression.Parameter(typeofT)
};
静态只读Func _orFunc=Expression.Lambda(
Expression.Convert(Expression.Or(
Expression.Convert(参数[0],underyingType),
Expression.Convert(参数[1],参考类型)
),typeofT),参数);
公共静态函数或函数{get{return\u orFunc;}}
}
您可以创建一个静态助手方法,为聚合生成所需的或函数。该函数在首次访问时生成,并缓存以供其他使用
这假定传递的类型将是枚举
public T CombineFlags<T>(params T[] flags)
where T : struct, IConvertible
{
return flags.Select(flag => flag).Aggregate(EnumHelper<T>.OrFunction);
}
private class EnumHelper<T>
where T : struct,IConvertible
{
static readonly Type typeofT = typeof(T);
static readonly Type underlyingType = Enum.GetUnderlyingType(typeofT);
static readonly ParameterExpression[] parameters =
{
Expression.Parameter(typeofT),
Expression.Parameter(typeofT)
};
static readonly Func<T, T, T> _orFunc = Expression.Lambda<Func<T, T, T>>(
Expression.Convert(Expression.Or(
Expression.Convert(parameters[0], underlyingType),
Expression.Convert(parameters[1], underlyingType)
), typeofT), parameters).Compile();
public static Func<T, T, T> OrFunction { get { return _orFunc; } }
}
public T组合标志(参数T[]标志)
其中T:struct,IConvertible
{
返回flags.Select(flag=>flag.Aggregate(EnumHelper.OrFunction);
}
私有类枚举帮助器
其中T:struct,IConvertible
{
静态只读类型typeofT=typeof(T);
静态只读类型underyingtype=Enum.getunderyingtype(typeofT);
静态只读参数expression[]参数=
{
表达式参数(typeofT),
Expression.Parameter(typeofT)
};
静态只读Func _orFunc=Expression.Lambda(
Expression.Convert(Expression.Or(
Expression.Convert(参数[0],underyingType),
Expression.Convert(参数[1],参考类型)
),typeofT),参数);
公共静态函数或函数{get{return\u orFunc;}}
}
您不能-运算符是静态的,编译器无法猜测传入的是什么-它们可能不支持
运算符。您可以尝试将值转换为长的,执行此操作并将其转换回。您不能-运算符是静态的,编译器无法猜测传入的t-它们可能不支持
运算符。您可以尝试的一件事是将值转换为long
,执行此操作并将其转换回。long可能更安全。long可能更安全。