I have a couple of function like CallMyFunction
in my codebase. I would like to refactor them into one generic function
enum MyEnum
{
ValueA,
ValueB,
ValueC
}
static void MyFunction<T>()
{
//...
}
static void CallMyFunction(MyEnum myEnum)
{
switch (myEnum)
{
case MyEnum.ValueA:
MyFunction<A>();
break;
case MyEnum.ValueB:
MyFunction<B>();
break;
case MyEnum.ValueC:
MyFunction<C>();
break;
}
}
I would like to be able to have something like
//I would like to make it work for Func<T> too
static void GenericCall(MyEnum myEnum, Action<?????> myFunc)
{
switch (myEnum)
{
case MyEnum.ValueA:
myFunc<A>();
break;
case MyEnum.ValueB:
myFunc<B>();
break;
case MyEnum.ValueC:
myFunc<C>();
break;
}
}
//And then call it like this
GenericCall(myEnum, MyFunction);
GenericCall(myEnum, AnotherFunction);
I would simply create a dictionary of myenum/action pairs
Your dictionary:
Dictionary<MyEnum,Action> actions = new Dictionary<MyEnum,Action>()
{
{ValueA, ()=>{your code...}},
{ValueB, ()=>{your code...}}
};
calling a method
static void CallMyFunction(MyEnum myEnum)
{
actions[myEnum]();
}
In your example, there are no parameters for any calls to MyFunction<>
, meaning there are no generic arguments required for Action
. Likewise, you cannot change to CallMyFunction<T>
as T
changes depending on the enum
.
As for <A>
, <B>
and <C>
, these have to be specified in each case
rather than put in as part of a generic argument to Action
. The switch
is calling the methods, not the caller of GenericCall
. It's this key point that you're working around, to dynamically select <A>
, <B>
and <C>
based on the enum
value.
Trying to put an argument into CallMyFunction
for myFunc
effectively means the caller has to supply the types A
, B
and C
which negates the purpose of the switch
. This isn't what you're trying to do I think.
One way of refactoring would be to change the method MyFunction<T>
to take the type parameter as a parameter rather than a generic. This would allow you to do the following;
enum MyEnum
{
ValueA,
ValueB,
ValueC
}
static void MyFunction(Type type)
{
//...
}
static void CallMyFunction(MyEnum myEnum)
{
Type type;
switch (myEnum)
{
case MyEnum.ValueA:
type = typeof(A);
break;
case MyEnum.ValueB:
type = typeof(B);
break;
case MyEnum.ValueC:
type = typeof(C);
break;
}
MyFunction(type);
}
However this doesn't really save you anything.
To get proper value out of it, you could create a custom Attribute
that took a constructor argument of Type
and apply the Attribute
directly to the enum
. Your function MyFunction
, could be modified to check for the Attribute
on the enum and correctly pass the correct type to MyFunction
.
That said, it'd only be worth it if you had a large (>10) enum
values/types. The structure as it stands is fairly straight forward and easy (if mundane), to maintain.
It's worth mentioning that you could also use reflection to call MyFunction<>
and supply the generic argument at runtime but you'd still be left with picking out the type by enum
. It would add more code to maintain rather than reduce it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.