1

I have a program that has to execute a function acording to a Enum and I'm wondering If there's another way to it than this:

enum FunctionType
{
 Addition = 0,
 Substraction = 1,
 Mutiplication = 2,
 Division = 3
}
void ExecuteFunction(FunctionType Function)
{
  switch(Function)
  {
    case FunctionType.Addition: Addition();
    break;
    case FunctionType.Substraction: Subsctration();
    break;      
    ...
    default: ...  
  }
}

(This is not the code i'm using, it's just to represent what I want to do). This approach should work fine, but what happens when you have much more functions? I don't want to have a 50 line switch. So I want to know if there's a way to simplify it, something like this maybe:

enum FunctionType : Action
{
 Addition = new Action(Addition);
 Substraction = new Action(Substraction);
 ....
}
void ExecuteFunction(FunctionType Function)
{
 (Action)Function.Invoke();
}

No switch is needed and what could be 50 lines turn into 1 line. But this is not possible to do, only numeric types are acceped as enums. I think it's posible to have a List<T> of actions but that would require to add each action to the list at runetime.

EDIT: I've found on a source code a way this is done, but I can't really understand It. This is what I get: They create a custom Attribute that contains a string (The method name) and on the methods they do:

[CustomAtrribute("name")]
void Method()
{    
}

Then I don't know how this is called by it's name, I guess some kind of refelction, bu I don't know how to find the info about this.

EDIT2: I found the way I want to do this, I'll add an interface with a function, then implement that interface with the code inside the function and Use a Dictionary<Enum, Interface> to call it. I don't know If I should answer my own question, anyways, thanks to everyone one helped me.

Pau C
  • 773
  • 4
  • 20
  • 4
    Well you could have a `Dictionary`... but again, you'd need to build it up at execution time. If the method names all match the enum value names, you could do that via reflection though. – Jon Skeet Aug 19 '16 at 09:30
  • You can run an action by just appending `()`, no need to do `.Invoke()`. Just an fyi – vrwim Aug 19 '16 at 09:47
  • @Jon Skeet Maybe the dictionary thing works fine, but adding everything doesn't sound good. Still better than a gigantic switch though. Making every method name match every enum name sounds a little dangerous when adding new things – Pau C Aug 19 '16 at 09:51
  • Well you could add a unit test for it, of course. Ultimately, you haven't told us why you have the enum to start with. Why can your `ExecuteFunction` method not just take an `Action` or whatever? – Jon Skeet Aug 19 '16 at 11:27
  • I want to do this on a server and each value in the enum corresponds to a different type of packet, each packet is identified by a `int` value and parsed into the Enum. With a few diferent types of packets a switch would be just fine, but as I update the program I want to add more packets, and I want the code to be "clean", not a 50 case switch – Pau C Aug 19 '16 at 11:37
  • Careful, parsing enums can be tricky: http://stackoverflow.com/questions/28219215/is-this-a-bug-in-c-sharp-enum-parse – argyle Aug 19 '16 at 18:00
  • I'm just casting them from a int, and I check first if the value exists. But thanks. – Pau C Aug 19 '16 at 18:01

2 Answers2

3

Can't say I would recommend doing this but:

public static class Functions
{
    public static Func<int, int, int> Add = (x, y) => { return x + y; };
}

Then you just call Functions.Add(1,1)

If you really have to use an enum for it then you could do:

public static class Functions
{
    public static void Add()
    {
        Debug.Print("Add");
    }

    public static void Subtract()
    {
        Debug.Print("Subtract");
    }

    public enum Function
    {
        Add,
        Subtract
    }

    public static void Execute(Function function)
    {
        typeof(Functions).GetMethod(function.ToString()).Invoke(null, null);
    }
}

Then Functions.Execute(Functions.Function.Add) (extra functions is because my enum was inside the Functions class).

Dave Williams
  • 2,166
  • 19
  • 25
  • This looks interesting, but would this have a performance impact when being called many times? Also why `.Invoke(null, null);`? – Pau C Aug 19 '16 at 11:27
  • I tested this and the performance impact is pretty big, It takes x30 time if I input the name function as a string and x133 if I do `.ToString()` compared the regular function calling. If I load the methodInfo first it takes x20 time. – Pau C Aug 19 '16 at 11:45
  • @null `.Invoke(null,null)` to call static method with no args, you may need to change it for your thing. Performance using reflection will be impacted heavily. I did say I suggest you don't. It might be worth examining if you are doing it the right way if you feel you need reflection. I can only answer your question because I don't know what you are trying to accomplish. All that said, the performance penalty may be acceptable depending on your situation. Don't optimise prematurely. – Dave Williams Aug 21 '16 at 16:13
  • I found a way to do what I wanted, I set a custom attribute with a string to the "functions" then I use reflection to get all functions with that attribute and add the to a Dictionary so there's not that big of a performance impact, since I only use reflection once. – Pau C Aug 22 '16 at 07:44
0

If your functions contain same signature then you can do something like this

enum FunctionType
{
 Addition = 0,
 Substraction = 1,
 Mutiplication = 2,
 Division = 3
}
void ExecuteFunction(FunctionType Function)
{
  //variable will contain function to execute
  public Func<int, int, int> functionToExecute= null;

  switch(Function)
  {
    case FunctionType.Addition: functionToExecute=Addition;
    break;
    case FunctionType.Substraction: functionToExecute=Subsctration;
    break;      
    ...
    default: ...  
  }

  //Checking if not reached default case
  if(functionToExecute!=null)
  {
   var result= functionToExecute(para1,para2);
   ...............
  }


}
Moumit
  • 8,314
  • 9
  • 55
  • 59
  • I am trying to avoid the switch, that's the problem in the first place. If I have many functions the code would be too long. – Pau C Aug 19 '16 at 11:15