c# - 允许按位运算的通用约束?

标签 c# generics enums

我有一个枚举:

  public enum Flags {
        COMMAND_MSG = 1,
        COMMAND_FILE = 2,
        COMMAND_ACTION = 4,
      }

现在,假设我设置了多个值,例如:

Flags g = Flags.COMMAND_ACTION |Flags.COMMAND_MSG; 

所以我有一个值为 5 的 int。

现在,从 5 我想看到它是以下内容的组合:Flags.COMMAND_ACTION |Flags.COMMAND_MSG;

(注意,我没有[Flags] 属性,因为我使用的是 protobuff 库,并且枚举是自动生成的

我尝试了什么:

public string Show (Flags item)
{
  var s="";
  string.Join(",", Enum.GetValues(typeof(Flags))
        .Cast<Flags>() 
        .Select(f=>(f & item) >0 ?f.ToString() :"") //check if bit is set
        .Where(f=>!string.IsNullOrWhiteSpace(f))); //remove empty
  return s;
}

所以 Show(5); 确实显示:COMMAND_MSG,COMMAND_ACTION

那么问题出在哪里?

我想将其转换为通用扩展方法:

 public static string ToFlags<T>(this int val, T FlagType) where T : ??

    {
        return string.Join(",", Enum.GetValues(typeof(T))
                     .Cast<T>()
                     .Select(enumEntry => (enumEntry & val) > 0 ? enumEntry.ToString() : "")
                     .Where(f => !string.IsNullOrWhiteSpace(f)));
    }

但是有一个错误,因为:

enter image description here

问题:

我应该应用哪个通用约束才能使其正常工作?

最佳答案

对于这种情况没有合适的通用类型约束。您可以将位运算应用于 int,因此将枚举值转换为 int。 T 不能直接转换为int;但是,您可以绕过 object

public static string ToFlags<T>(this T val)
    where T : struct
{
    return string.Join(",", Enum.GetValues(typeof(T))
                 .Cast<T>()
                 .Select(enumEntry => ((int)(object)enumEntry & (int)(object)val) > 0
                             ? enumEntry.ToString() : "")
                 .Where(f => !string.IsNullOrWhiteSpace(f)));
}

注意:数字也有类似的情况。您不能说 where T : number 并对类型 T 的值应用数字运算符。

您还可以将 val 设为 T 并且您不必将 T 的类型作为方法参数传递。您已经将其作为通用类型参数传递。这已经足够了。编译器也很聪明,可以推断出 T,因此您不必在调用方法时指定它。

// Test
Flags item = Flags.COMMAND_ACTION | Flags.COMMAND_MSG;
Console.WriteLine(item.ToFlags());

您可以将struct 指定为泛型类型约束,因为struct 代表值类型。它并不完美,但总比没有约束要好。

关于c# - 允许按位运算的通用约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27657323/

相关文章:

c# - 将一个服务注入(inject)另一个服务

C++ 泛型插入排序

c# - 如何将 `where T : U` 泛型类型参数约束从 C# 转换为 F#?

java - 如何在泛型类中使用 Enum 的静态函数?

c++ - 在 Selene 中包装一个枚举以便在 Lua 中访问

c# - 通过 AsterNET 管理 VoIP 调用

c# - 单元/集成测试中的反射问题

java - ServiceLoader,其中类型 parm 本身是通用的

Java 枚举属性根据访问顺序返回 null

c# - Asp.NET MVC 5 IdentityServer4 外部供应商