8

I am curious how would you maintain your code once you throw a System.ComponentModel.InvalidEnumArgumentException.

Basically I have a switch statement like this:

switch (enumValue)
{
    case MyEnum.Value1:
        break;

    case MyEnum.Value2:
        break;

    default:
        throw new InvalidEnumArgumentException();
}

What if I decide to add more values to MyEnum in the future, for example, Value3 and Value4? That would mean I would end up throwing a misleading exception. How would I prevent this?

Should I use reflection before throwing? What exception should I throw in this case? I'm looking for suggestions.


I just discovered this exception a couple minutes ago so maybe I am looking at this in the wrong context. Is this exception thrown when a certain enum argument is not supported (in which case Value3 and Value4 would not be supported)?

Marlon
  • 19,924
  • 12
  • 70
  • 101

6 Answers6

11

The problem you state depends on the context, if a method receives an enumeration as an argument it must specify what values does it support and what it does with an unknown enumeration value.

If you add more enumeration options you need to decide what to do even if you were not throwing an exception in the default case.

Be reminded that the exception is special helpful since you can pass any integer as an enumeration value.

For example:

enum Foo { A, B }

static int Bar(Foo f)
{
    switch (f)
    {
        case Foo.A:
            return 1;
        case Foo.B:
            return 2;
        default:
            throw new InvalidEnumArgumentException("f", (int)f, typeof(Foo));
    }
}

static void Main()
{
    Bar(Foo.A);
    Bar((Foo)99);
}
João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • 7
    A slight improvement on the example if you are only targeting dot net 4.6 or above is to replace the `"f"` string with `nameof(f)`. – skkeeper Jul 23 '15 at 13:53
5

What if I decide to add more values to MyEnum in the future, for example, Value3 and Value4? That would mean I would end up throwing a misleading exception. How would I prevent this?

When you're using InvalidEnumArgumentException the key thing to understand is argument. By throwing the exception you are saying that the argument for the method was invalid. (InvalidEnumArgumentException derives from ArgumentException.) It doesn't necessarily mean that the value was not a member of the enum. So I would not consider it misleading.

jackvsworld
  • 1,453
  • 15
  • 17
0

I wouldn't be using that exception you're using in that context. By virtue of enumValue being of type MyEnum (I presume?) it can never contain an invalid enum value. If you have switches based on the value of the enum which need to fail if they don't recognise the value then you'll need to throw an appropriate exception (maybe just a normal ArgumentException?) but in most cases I guess you'd let the code run do nothing for an unknown enum value.

DoctorMick
  • 6,703
  • 28
  • 26
  • 2
    This is incorrect. According to [this addition to the design guidelines](http://blogs.msdn.com/b/kcwalina/archive/2004/05/18/134208.aspx), "It is legal to cast any integer value into an enum even if the value is not defined in the enum.". – Anders Fjeldstad Jul 01 '11 at 10:18
  • Of course an `enum` value can be invalid. You can cast a number that is not one of the enumeration values to an `enum` type. Or this could be caused by having an enumeration defined in a different assembly which was updated with an expanded enumeration. – Allon Guralnek Jul 01 '11 at 10:20
  • 1
    Well I never. Looks like I've learned something new today. :-) – DoctorMick Jul 01 '11 at 12:51
0

You are using the exception in a wrong way:

http://msdn.microsoft.com/en-us/library/system.componentmodel.invalidenumargumentexception.aspx

This exception is thrown if you pass an invalid enumeration value to a method or when setting a property.

Petar Ivanov
  • 91,536
  • 11
  • 82
  • 95
0

I believe you are looking it in the wrong context, if these weren't enum but some specific values which were based on some business rule, so in such cases as the rules increase you would touch up relevant codes like these to incorporate the new ones. So if you are modifying the Enum then you should be look around for changes like these.

V4Vendetta
  • 37,194
  • 9
  • 78
  • 82
  • if there are lots of places with such switch statements acting on the same enum, one can have factory which creates polymorphic objects based on enum value, and move that functionality from switches to methods of that object – driushkin Jul 01 '11 at 10:26
-1

To validate the incoming enumeration value use the following static method...

public void MyMethod(MyEnum e)
{
    if (!Enum.IsDefined(typeof(MyEnum), e))
        throw new InvalidEnumArgumentException("e", (int)e, typeof(MyEnum));

...and you do not need to alter the check if new enum values are added in the future.

Phil Wright
  • 22,580
  • 14
  • 83
  • 137
  • 2
    If MyEnum is extended with new values, the `!Enum.IsDefined(typeof(MyEnum), e))` will return true for them, so this test most likely will never fail. – Spook Jan 15 '13 at 13:48
  • @Spook but it will fail if MyEnum doesn’t define an entry for `0` and e gets implicitly assigned a default value in `MyEnum e; MyMethod(e);` or when code sets `e`’s value numerically. The point is that C# itself does not force `e` to be a valid value for `MyEnum` and, simply, you cannot assume anything. – binki Feb 07 '14 at 19:32