通用枚举作为方法参数

16

给定一个构造函数

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

5
当您传参时,可以将参数接收为整数,并将您的枚举类型转换为整数。 - Martin Verjans
你无法在C#中使用通用构造函数。你所能做的最好的办法是编写一个非通用的基类,再加上一个通用的子类,然后将枚举类型作为通用子类的类型参数。有些别扭。MyBase b = new MySub<EnumA>(EnumA.SomeValue); int n = b.ID; - 15ee8f99-57ff-4f92-890c-b56153
MyObject(MyEnum1 enum1Selection){} 但是整数更好 - Shannon Holsinger
new MyObject((int)MyEnum1.Something); - Thomas Ayoub
点赞@SuperPeanut,但是我会创建一个“objectType”枚举,并将其传递给一个工厂,该工厂进而使用正确的“enum”参数创建正确的东西。var newObject = myFactory.Create(ObjectType.One) - radarbob
或者,重载构造函数。 - radarbob
5个回答

10

另一个选项是:

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

通过这种方法,您可以像您要求的那样使用它,而无需每次调用构造函数时都进行整型转换:

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

7
为什么要传递枚举,而不是传递整数?
var newObject = new MyObject((int)MyEnum1.Something);
var anotherObject = new MyObject((int)MyEnum2.Dodo);

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

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

3
是的,这正是我已经在做的事情,如果我可以直接传递枚举,它看起来会更易读。 - Tom Gullen
如果关注可读性,您可以使用@HimBromBeere的解决方案,它具有通用构造函数,您需要两次编写枚举名称,但看起来很好...一切都取决于您想要什么。 - Martin Verjans
因为Enum可以有属性“Flags”。 - Dmitry

6

只需使用通用构造函数:

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

更简单的方法是将枚举作为整数传递给构造函数,如其他答案中所述。

编辑:自C# 7.3起,您可以立即使用枚举约束:

class MyObject<T> where T: Enum { ... }

你知道你不能将枚举用作约束条件吗?如果可以的话,生活会更容易,但它不会编译。 - Ben
@Ben 你说得对,我已经适当地更新了答案。不幸的是,使用这种方法会失去对 Enum 的编译器类型检查,从而使得将 int 实例传递给该方法成为可能。 - MakePeaceGreatAgain
我非常清楚这一点。我的一天都在努力寻找尽可能强大的解决方案。但遗憾的是,以上提到的就是你能得到的最好的! - Ben

-1

如果你真的需要让这个调用适用于各种类型,那么我认为你应该使用:

  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; // 可能会抛出InvalidCast!
                    return result;
                }
                catch
                {
                    throw;
                }
            }
            else
            {
                throw new InvalidCastException("底层类型肯定无法转换为Int32!");
            }
        }
        else
        {
            throw new InvalidCastException("不是枚举!");
        }
    }
    

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


我几乎可以肯定,您可以添加许多不同的检查并在多年内完善此代码 =) - Sergey.quixoticaxis.Ivanov
是的,传递一个整数会更容易。 - Sergey.quixoticaxis.Ivanov

-2
你是在使用属性枚举还是参数?
public enum Enum1{}
public Enum1 enum1 { get;set; }
public MyObject()
{
   ID = (int)enum1;
}

试一试吧。希望它有用。


它究竟如何回答他的问题? - Eric Wu
从构造函数访问成员属性,你会得到什么结果? - Sergey.quixoticaxis.Ivanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接