将枚举值的通用列表组合为单个值的 C# 方法

标签 c#

我要传一个IEnumerable<T>枚举值(枚举具有 Flags 属性)并返回聚合值。下面的方法有效,但前提是枚举使用默认值 Int32类型。如果它使用 byteInt64它不会工作。

public static T ToCombined<T>(this IEnumerable<T> list) where T : struct
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("The generic type parameter must be an Enum.");
    var values = list.Select(v => Convert.ToInt32(v));
    var result = values.Aggregate((current, next) => current | next);
    return (T)(object)result;
}

我知道我可以获得基础类型:
Type enumType = typeof(T);
Type underlyingType = Enum.GetUnderlyingType(enumType);

但我不知道如何在方法中使用它。我如何制作扩展方法以便它可以处理任何 enums 的列表带有标志属性?

更好,但可能是非常大的 UInts 的问题
public static T ToCombined<T>(this IEnumerable<T> list) where T : struct
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("The generic type parameter must be an Enum.");
    var values = list.Select(v => Convert.ToInt64(v));
    var result = values.Sum();
    var underlyingType = Enum.GetUnderlyingType(typeof(T));
    return (T)Convert.ChangeType(result, underlyingType);
}

谢谢
安德鲁

最佳答案

此解决方案将转换内联到基础类型并返回到表达式中的枚举类型。

public static T ToCombined<T>(this IEnumerable<T> list)
    where T : Enum
{
    Type underlyingType = Enum.GetUnderlyingType(typeof(T));

    var currentParameter = Expression.Parameter(typeof(T), "current");
    var nextParameter = Expression.Parameter(typeof(T), "next");

    Func<T, T, T> aggregator = Expression.Lambda<Func<T, T, T>>(
        Expression.Convert(
            Expression.Or(
                Expression.Convert(currentParameter, underlyingType),
                Expression.Convert(nextParameter, underlyingType)
                ),
            typeof(T)
            ),
        currentParameter,
        nextParameter
        ).Compile();

    return list.Aggregate(aggregator);
}

请注意,我使用了 C# 7.3 Enum类型约束。如果您不使用 C# 7.3,struct约束与 IsEnum检查仍然是要走的路。

关于将枚举值的通用列表组合为单个值的 C# 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53636974/

相关文章:

c# - 从共享邮箱使用 C# 中的 EWS 发送电子邮件

c# - Range.Value 在 VBA 和 C# 中产生不同的结果

c# - 编译器错误消息 : CS0246: when I renamed my project

c# - 'Lucene.Net.Store.FSDirectory' 的类型初始值设定项抛出异常

c# - Windows Workflow Runtime 能否同时运行 2 个工作流

c# - 将 POCO 对象类和 DBContext 从 Entity Framework 6 模型中分离出来

c# - 跟踪工作簿和工作表重命名

c# - 每个都有一个动态列表?

c# - ASMX 后响应正文缺少最后一个字符

c# - 验证 if 子句中的空查询