【问题标题】:Generic enum as method parameter通用枚举作为方法参数
【发布时间】:2016-09-08 13:26:30
【问题描述】:

给定一个构造函数

public MyObject(int id){
    ID = id;
}

还有两个枚举:

public enum MyEnum1{
    Something = 1,
    Anotherthing = 2
}

public enum MyEnum2{
    Dodo = 1,
    Moustache= 2
}

是否可以将泛型枚举作为构造函数的参数传入?我正在寻找以下方面的解决方案:

public MyObject(enum someEnum){
    ID = (int)someEnum;
}

所以你可以这样做:

var newObject = new MyObject(MyEnum1.Something);
var anotherObject = new MyObject(MyEnum2.Dodo);

【问题讨论】:

  • 您可以接收整数形式的参数,并在传递时将您的枚举转换为整数。
  • You can't do a generic constructor in C#。你能做的最好的事情是用一个泛型子类编写一个非泛型基类,然后使枚举类型成为泛型子类的类型参数。尴尬的。 MyBase b = new MySub<EnumA>(EnumA.SomeValue); int n = b.ID;
  • MyObject(MyEnum1 enum1Selection){} 但整数更好
  • new MyObject((int)MyEnum1.Something); ?
  • 支持@SuperPeanut,但是,我会创建一个“objectType”enum 并将其传递给工厂,该工厂又使用正确的enum 参数创建正确的东西。 var newObject = myFactory.Create(ObjectType.One).

标签: c# generics enums


【解决方案1】:

另一种选择是:

public MyObject(Enum someEnum){
    ID = Convert.ToInt32(someEnum);
}

这样您就可以按照您的要求使用它,而不必每次调用您的构造函数时都转换为int

var newObject = new MyObject(MyEnum1.Something);
var anotherObject = new MyObject(MyEnum2.Dodo);

【讨论】:

    【解决方案2】:

    为什么要传递枚举,而可以传递整数?

    var newObject = new MyObject((int)MyEnum1.Something);
    var anotherObject = new MyObject((int)MyEnum2.Dodo);
    

    并使用您的第一个构造函数:

    public MyObject(int id){
        ID = id;
    }
    

    【讨论】:

    • 是的,这就是我已经在做的事情,如果我可以直接传递枚举,看起来会更具可读性
    • 如果是关于可读性,你可以使用@HimBromBeere solution 和泛型构造函数,你必须写两次枚举名称,但看起来没问题......一切都取决于你想要什么
    【解决方案3】:

    只需使用通用构造函数:

    class MyObject<T> {
    
        public MyObject(T someEnum) where T : struct, IConvertible
        {
            if (!typeof(T).IsEnum) 
                throw new ArgumentException("Not an enum");
            ID = Convert.ToInt32(someEnum);
        }
    }
    

    现在您可以轻松地这样称呼它:

    var m = new MyObject<MyEnum>(MyEnum1.Something);
    

    但更简单的方法是将枚举作为整数传递给其他答案中提到的构造函数。

    【讨论】:

    • 您知道不能使用 Enum 作为约束吗?如果可以,生活会更轻松,但它不会编译。
    • @Ben 你是对的,我适当地更新了答案。不幸的是,您使用这种方法失去了对Enum 的编译器类型检查,因此也可以将int 的实例传递给该方法。
    • 我很痛苦地意识到了这一点。我的一天一直在努力寻找尽可能强大的解决方案。但遗憾的是,上面的内容和你得到的一样好!
    【解决方案4】:

    好吧,如果您确实需要将此调用通用化为多种类型,那么恕我直言,您应该使用:

    1. Type.IsEnum 检查您的论点是否真的是 Enum
    2. Enum.GetUnderlyingType 知道你的论点基于什么类型(不一定是Int32);
    3. 现在投射你的对象。

      public static Int32 GetAnInt<T>(T arg) where T : struct
      {
          if ((typeof(T).IsEnum))
          {
              var underlyingType = typeof(T).GetEnumUnderlyingType();
              if (underlyingType == typeof(Int32)
              || underlyingType == typeof(Int16)) //etc.
              {
                  try
                  {
                      dynamic value = arg;
                      var result = (Int32)value; // can throw InvalidCast!
                      return result;
                  }
                  catch
                  {
                      throw;
                  }
              }
              else
              {
                  throw new InvalidCastException("Underlying type
                               is certainly not castable to Int32!");
              }
          }
          else
          {
              throw new InvalidCastException("Not an Enum!");
          }
      }
      

      这样你就可以实现优美的语法:var j = GetAnInt(MyEnum.FirstValue);

    【讨论】:

    • 而且我几乎可以肯定,您可能会添加许多不同的检查并优化此代码多年 =)
    • 是的,传递整数更容易。
    【解决方案5】:

    你是在使用属性枚举还是参数。

    public enum Enum1{}
    public Enum1 enum1 { get;set; }
    public MyObject()
    {
       ID = (int)enum1;
    }
    

    试试吧。希望有用。

    【讨论】:

    • 究竟如何回答他的问题?
    • 从构造函数访问成员属性会得到什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    相关资源
    最近更新 更多