简体   繁体   English

将通用类型参数传递给Func

[英]Pass generic type parameter to Func

I have a couple of function like CallMyFunction in my codebase. 我的代码库中有几个函数,例如CallMyFunction 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 . 在您的示例中,对MyFunction<>任何调用都没有参数 ,这意味着Action不需要通用参数。 Likewise, you cannot change to CallMyFunction<T> as T changes depending on the enum . 同样,您不能更改为CallMyFunction<T>因为T取决于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 . 至于<A><B><C> ,必须在每种case都指定它们,而不是将其作为Action泛型参数的一部分放入。 The switch is calling the methods, not the caller of GenericCall . switch正在调用方法,而不是GenericCall的调用者。 It's this key point that you're working around, to dynamically select <A> , <B> and <C> based on the enum value. 这就是您要解决的关键点,它可以基于enum值动态选择<A><B><C>

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 . 试图为myFunc CallMyFunction加上一个参数,实际上意味着调用者必须提供ABC类型,这会否决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. 重构的一种方法是更改​​方法MyFunction<T>以将类型参数作为参数而不是泛型。 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 . 为了从中获得适当的价值,您可以创建一个自定义Attribute ,该Attribute采用Type的构造函数参数,并将该Attribute直接应用于enum Your function MyFunction , could be modified to check for the Attribute on the enum and correctly pass the correct type to MyFunction . 您可以将函数MyFunction修改为检查枚举中的Attribute ,并将正确的类型正确传递给MyFunction

That said, it'd only be worth it if you had a large (>10) enum values/types. 也就是说,仅当enum值/类型较大(> 10)时,才值得这样做。 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 . 值得一提的是,您还可以使用反射来调用MyFunction<>并在运行时提供泛型参数,但是您仍然可以通过enum选择类型。 It would add more code to maintain rather than reduce it. 它将添加更多代码来维护而不是减少代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM