C# 将泛型类型参数传递给Func

C# 将泛型类型参数传递给Func,c#,generics,func,C#,Generics,Func,我的代码库中有两个函数,比如CallMyFunction。我想把它们重构成一个通用函数 enum MyEnum { ValueA, ValueB, ValueC } static void MyFunction<T>() { //... } static void CallMyFunction(MyEnum myEnum) { switch (myEnum) { case MyEnum.ValueA:

我的代码库中有两个函数,比如
CallMyFunction
。我想把它们重构成一个通用函数

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;                                                              
    }
}
enum MyEnum
{
瓦卢亚,
瓦卢布,
瓦卢克
}
静态函数()
{
//...
}
静态void CallMyFunction(MyEnum MyEnum)
{
开关(myEnum)
{
案例MyEnum.ValueA:
MyFunction();
打破
案例MyEnum.ValueB:
MyFunction();
打破
案例MyEnum.ValueC:
MyFunction();
打破
}
}
我希望能有这样的东西

//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);
//我想让它也为Func工作
静态void GenericCall(MyEnum MyEnum,Action myFunc)
{
开关(myEnum)
{
案例MyEnum.ValueA:
myFunc();
打破
案例MyEnum.ValueB:
myFunc();
打破
案例MyEnum.ValueC:
myFunc();
打破
}
}
//然后像这样称呼它
GenericCall(myEnum,MyFunction);
GenericCall(myEnum,另一个函数);

在您的示例中,对
MyFunction
的任何调用都没有参数,这意味着
操作
不需要通用参数。同样,您不能更改为
CallMyFunction
,因为
T
的更改取决于
enum

对于
,必须在每个
案例中指定它们,而不是作为
操作的通用参数的一部分。
开关
正在调用方法,而不是
GenericCall的调用方
。这是您正在解决的关键点,根据
枚举
值动态选择

尝试将参数放入
myFunc
CallMyFunction
中实际上意味着调用者必须提供类型
A
B
C
,这否定了
开关的用途。我想这不是你想做的

重构的一种方法是将方法
MyFunction
更改为将类型参数作为参数而不是泛型参数。这将允许您执行以下操作:

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);
}
然而,这并不能真正为你节省任何东西

为了从中获得适当的值,您可以创建一个自定义的
属性
,该属性采用
类型
的构造函数参数,并将
属性
直接应用于
枚举
。可以修改函数
MyFunction
,以检查枚举上的
属性
,并将正确的类型正确传递给
MyFunction

也就是说,只有当您有一个大(>10)
enum
value/type时,才值得这么做。目前的结构相当简单,易于维护(如果很普通的话)


值得一提的是,您还可以使用反射来调用
MyFunction
,并在运行时提供泛型参数,但仍然需要通过
enum
来选择类型。它将添加更多代码来维护,而不是减少代码。

我只需创建一个myenum/action对字典

你的字典:

Dictionary<MyEnum,Action> actions = new Dictionary<MyEnum,Action>()
{
    {ValueA, ()=>{your code...}},
    {ValueB, ()=>{your code...}}
};

根据以下内容:,这可能会影响性能。@KOTIX我同意如果您有数百万个交换机案例。@KOTIX,您也会有lambda的性能开销。如果您对性能开销还满意的话,这是一种相当干净的方法。@DiskJunky lamda查询只是编译时确定的函数调用。不是什么大话题
x=>x==1
仅等于
delegate(inti){return x==1;}
@Bruno问题是你的,使用与否,但你之前评论中的所有参数都是无效的(关于安全性、代码重复等。我认为你对这个答案理解不够)
static void CallMyFunction(MyEnum myEnum)
{
    actions[myEnum]();
}