通用约束是否允许按位操作? [英] Generic Constraint for allowing bitwise operations?

查看:67
本文介绍了通用约束是否允许按位操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举

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

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

Now , suppose I set multiple values like :

Flags g = Flags.COMMAND_ACTION |Flags.COMMAND_MSG; 

所以我有一个int,其值 5

So I have an int with value 5.

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

Now , from that 5 I want to see that it's a combination of : Flags.COMMAND_ACTION |Flags.COMMAND_MSG;

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

(Notice , I dont have [Flags] attribute because I'm using protobuff library , and the enum is auto generated.

我有什么尝试过:

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

那么问题出在哪里?

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

I wanted to convert it to a generic extension method :

 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)));
    }

但是有一个错误,因为:

But there's an error because :

问题:

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

Which generic constraint should I apply in order for this to work ?

推荐答案

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

There is no appropriate generic type constraint for this situation. You can apply bitwise operations to ints, so convert the enum value to int. T cannot be cast to int directly; however, you can make the detour over 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)));
}

注意:数字也存在类似情况。您不能说其中T:数字并在类型T的值上应用数字运算符。

Note: There is a similar situation with numbers. You can't say where T : number and apply numeric operators on values of type T.

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

Also you can make val a T and you don't have to pass the type of T as method argument. You are passing it as generic type argument already. This is sufficient. The compiler is also smart enough to infer T, so you don't have to specify it when calling the method.

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

您可以指定 struct 作为通用类型约束,如 struct 代表值类型。它不是完美的,但总比没有约束要好。

You can specify struct as generic type constraint, as struct stands for value types. It is not perfect, but better than no constraint at all.

这篇关于通用约束是否允许按位操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆