对于这种情况,没有适当的泛型类型约束。您可以应用按位运算int
s,因此将 enum 值转换为 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
a T
并且您不必传递类型T
作为方法参数。您已经将其作为泛型类型参数传递。这就足够了。编译器也足够聪明来推断T
,因此在调用该方法时不必指定它。
// Test
Flags item = Flags.COMMAND_ACTION | Flags.COMMAND_MSG;
Console.WriteLine(item.ToFlags());
您可以指定struct
作为泛型类型约束,作为struct
代表值类型。它并不完美,但比完全没有约束要好。
Update
距离提出这个问题已经过去很长时间了。 C#11 介绍接口中的静态虚拟成员 https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members和 .NET 7 BCL 接口IBitwiseOperators https://learn.microsoft.com/en-us/dotnet/api/system.numerics.ibitwiseoperators-3 and IEqualityOperators https://learn.microsoft.com/en-us/dotnet/api/system.numerics.iequalityoperators-3。这些接口(和许多其他人 https://learn.microsoft.com/en-us/dotnet/api/system.numerics) 是针对数字类型实现的,但遗憾的是不适用于枚举。
See: [API 提案]:Enum 应实现 IBitwiseOperators、IEqualityOperators #81664 https://github.com/dotnet/runtime/issues/81664.
从 C# 7.3 开始,有一个枚举通用约束 https://devblogs.microsoft.com/premier-developer/dissecting-new-generics-constraints-in-c-7-3/#the-enum-constraint除了可以指定struct
.