【问题标题】:Use Action<object> as method input使用 Action<object> 作为方法输入
【发布时间】:2014-02-20 14:06:20
【问题描述】:

我希望有一个可以将其他方法作为输入的方法。

输入法总是有一个单一的对象作为输入,但对象是不同的。

这或多或少是我需要做的:

public static void takeAnything(Action<object> inputFunc)
{
    Console.WriteLine(inputFunc.Method.Name);
}

public static void test1(MyOwnObject input){
    // Do stuff with input object
}

public static void test2(MyOtherOwnObject input){
    // Do stuff with input object
}

public static void startSystem(){
    takeAnything(test1);
    takeAnything(test2);
}

在这个虚拟案例中会写出:

test1
test2

我只是无法让它工作,所以非常感谢任何帮助。

编辑

我不知道这是否可能,也许不可能,但重要的是呼叫只是takeAnything(test1),而不是takeAnything&lt;MyOwnObject&gt;(test1) 或其他任何东西。

【问题讨论】:

  • 您遇到的具体问题是什么?您是否考虑过将TakeAnything 变成一个泛型方法(即TakeAnything&lt;T&gt;(Action&lt;T&gt; inputFunc)?
  • 我已经尝试过了,但我只能让它工作调用它:takeAnything(test),如果我删除 部分我得到这个错误:类型参数无法从用法中推断出方法“takeAnything(System.Action)”。尝试明确指定类型参数。我不知道这是否可能,这就是我希望你们能帮助我弄清楚:)

标签: c#


【解决方案1】:

让你的方法通用

public static void TakeAnything<T>(Action<T> inputFunc)
{
    Console.WriteLine(inputFunc.Method.Name);
}

当然,您将只能传递具有单个输入参数的方法。

更新:不幸的是,当您将方法组传递给方法时,C# 无法从用法推断动作泛型参数类型,因此使用它的唯一方法是手动指定泛型参数类型

takeAnything<MyOwnObject>(test)

详情见问题C# 3.0 generic type inference - passing a delegate as a function parameter

【讨论】:

    【解决方案2】:

    试试这个,这样你就可以将动态参数传递给动作:

    public static void takeAnything(Expression<Action> inputFunc)
    {
        var currentMethod = ((MethodCallExpression)inputFunc.Body);
        Console.WriteLine(currentMethod.Method.Name);
    }
    
    public static void test(MyOwnObject input){
        // Do stuff with input object
    }
    
    public static void startSystem(){
        MyOwnObject  yourObject = new MyOwnObject();
        takeAnything(() => test(yourObject));
    }
    

    【讨论】:

    • -1,您是否尝试过运行此代码?您认为 lambda 将如何在委托中表示?不,它不会神奇地消失,因此 Method.Name 可以解析为 "test"
    • 现在似乎可以工作了(takeAnything 中的参数名称与第一行中的使用不匹配的错字更正(actioninputFun)。
    • 抱歉,我编辑了我的答案。现在我认为是正确的
    • 感谢您的回答!对于我正在研究的解决方案,创建对象和东西的所有内容都不好。如果有可能,我希望能够做到:takeAnything(test)。但也许根本不可能:)
    • 删除 -1;然而,这种解决方案的缺点仍然是需要提供一些(可能是虚拟的)参数。我认为使用Action&lt;T1, ..., Tn&gt; 进行合理数量的重载是一个更好的选择。
    【解决方案3】:

    为什么不将takeAnything 方法的标题更改为:

    public static void takeAnything(Action<MyOwnObject> inputFunc)
    

    【讨论】:

    • 因为takeAnything方法会被很多不同的输入法调用,有不同的输入对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 2017-01-08
    • 2018-04-13
    • 2016-02-29
    相关资源
    最近更新 更多