16

Given a constructor

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

And two enums:

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

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

Is it possible to pass in a generic enum as a parameter of the constructor? I'm looking for a solution along the lines of:

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

So you can do:

var newObject = new MyObject(MyEnum1.Something);
var anotherObject = new MyObject(MyEnum2.Dodo);
6
  • 5
    You can receive the parameter as Integer, and convert your enums to Integers when you pass them. Commented Sep 8, 2016 at 13:28
  • You can't do a generic constructor in C#. The best you could do is to write a nongeneric base class with a generic subclass, then make the enum type a type parameter for the generic subclass. Awkward. MyBase b = new MySub<EnumA>(EnumA.SomeValue); int n = b.ID; Commented Sep 8, 2016 at 13:29
  • MyObject(MyEnum1 enum1Selection){} but integer is better Commented Sep 8, 2016 at 13:29
  • new MyObject((int)MyEnum1.Something); ? Commented Sep 8, 2016 at 13:31
  • upvote @SuperPeanut, but, I would create a "objectType" enum and pass that to a factory that in turn creates the right thing with the right enum parameter. var newObject = myFactory.Create(ObjectType.One).
    – radarbob
    Commented Sep 8, 2016 at 13:45

6 Answers 6

10

Another option would be:

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

This way you can use it like you requested without having to cast to int each time you call your contstructors:

var newObject = new MyObject(MyEnum1.Something);
var anotherObject = new MyObject(MyEnum2.Dodo);
1
  • I'm trying to do this in a ctor of a class and there it seems it won't allow that. Are methods and ctors different in that point? Edit: it seems Attributes are special there and it's not allowed there.
    – garcipat
    Commented Jun 11 at 9:38
7

Why do you want to pass the enums, while you could pass integers ?

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

and use your first constructor :

public MyObject(int id){
    ID = id;
}
3
  • 3
    Yup this is what I was doing already, would just look more readable if I could pass the enum in directly
    – Tom Gullen
    Commented Sep 8, 2016 at 13:58
  • If it is about readability, you can use @HimBromBeere solution with a generic constructor, you have to write the enum name twice but it looks all right... All depends on what you want Commented Sep 8, 2016 at 14:18
  • Because Enum can have attribute Flags
    – Dmitry
    Commented Mar 25, 2023 at 19:44
6

Just use a generic constructor:

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

Now you can easily call it like this:

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

But easier would be to pass the enum as integer to the constructor as mentioned in other answers.

EDIT: As of C# 7.3 you can use an enum-constraint right away:

class MyObject<T> where T: Enum { ... }
3
  • You know you can't use Enum as a constraint? Life would be easier if you could but it won't compile.
    – Ben
    Commented May 25, 2017 at 11:27
  • @Ben You´re right, I updated the answer appropriately. Unfortunately you´re loosing compiler-type check against Enum with this approach making it possible to pass instances of int to the method as well. Commented May 25, 2017 at 12:00
  • I am painfully aware of this. My day has been spent trying to find as robust of a solution as possible. But sadly the above is about as good as you'll get!
    – Ben
    Commented May 25, 2017 at 15:33
0

I have tried to do this with Attributes and it seems Enum as parameter in Attributes are not allowed. Therefore I had to do this workaround:

public MyCustomAttribute(object myEnumParameter)
{
    if (myEnumParameteris not Enum)
    {
        throw new ArgumentException("myEnumParameter is not an enum", 
            nameof(myEnumParameter));
    }

    MyEnumProperty = (Enum)myEnumParameter;
}
-1

Well, if you really need to make this call generic for a wide variety of types, then IMHO you should use:

  1. Type.IsEnum to check if your argument is really an Enum;
  2. Enum.GetUnderlyingType to know what type is your argument is based on (it's not necessarily an Int32);
  3. Now cast your object.

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

    That way you achieve the beautiful syntax of: var j = GetAnInt(MyEnum.FirstValue);

2
  • And I'm almost certain you may add a lot of different checks and polish this code for years =) Commented Sep 8, 2016 at 13:53
  • And yes, it's easier to pass an integer. Commented Sep 8, 2016 at 13:54
-2

Are you using properties enum or parameters.

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

Just try it. I hope it is useful.

2
  • How exactly does it answer his question?
    – Eric Wu
    Commented Sep 8, 2016 at 13:58
  • And what will you get accessing a member property from a constructor? Commented Sep 8, 2016 at 13:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.