【问题标题】:Using a delegate with varying parameters使用具有不同参数的委托
【发布时间】:2012-05-07 11:44:23
【问题描述】:

我想干燥我的源代码。假设我有一些主要在一行中不同的功能 - 我怎么能做到这一点??

public Result foo (int x, int y, int z){
    Log.Say("Foo started!");                                 <<< DIFFERENCE
    DoSomeMagic();
    try {
        result = controller.foo(x, y, z);                    <<< DIFFERENCE
    } catch (Exception){
        Log.Say("Something went terribly wrong");
    }
    return result;
}


public Result bar (Person a, string whatever){
    Log.Say("Bar started!");                                 <<< DIFFERENCE
    DoSomeMagic();
    try {
        result = controller.bar(a, whatever);                <<< DIFFERENCE
    } catch (Exception) {
        Log.Say("Something went terribly wrong");
    }
    return result;
}

这让我发疯了,因为它不可能那么难吗?我现在对各种方法感到困惑;到目前为止,我试图与代表一起做, Func、Lambda 表达式、匿名函数,但我就是无法让它工作(我想我需要休息一下)。

public Result handler (Func callbackMethodWithArgs) {
    Result result = null;
    Log.Say(method + " started!");
    DoSomeMagic();
    try {
        result = invoke(callbackMethodWithArgs) as Result;
    } catch (Exception) {
        Log.Say("Something went terribly wrong");
    }
    return result;
}

public Result foo (int x, int y, int z) {
    return handler(controller.foo(x, y, z));
}

public Result bar (Person a, string whatever) {
    return handler(controller.bar(a, whatever);
}

作为补充,可以使用匿名函数真的很棒,比如

public Result foo (int x, int y, int z) {
    return handler(delegate () {
        controller.foo(x, y, z));
        doSomethingOther();
    });
}

有什么建议吗??谢谢! (我阅读了许多关于类似主题的问题,但我没有找到任何解决问题的方法 - 所以我认为它可能是重复的 - 如果是这样,我很抱歉)

【问题讨论】:

    标签: c# delegates lambda dry anonymous-function


    【解决方案1】:

    您可以使用Func&lt;Result&gt;

    public Result handler (string name, Func<Result> method) {
        Result result = null;
        Log.Say(name + " started!");
        DoSomeMagic();
        try {
            result = method();
        } catch (Exception) {
            Log.Say("Something went terribly wrong");
        }
        return result;
    }
    

    然后在呼叫站点将他们变成代表:

    public Result foo (int x, int y, int z) {
        return handler("Foo", () => controller.foo(x, y, z));
    }
    
    public Result bar (Person a, string whatever) {
        return handler("Bar", () => controller.bar(a, whatever);
    }
    

    注意:如果您使用的是 .NET 2.0,则可以在使用上述代码之前手动创建 Func&lt;_&gt; 委托:

    public delegate TResult Func<TResult>();
    

    顺便说一句,以这种方式隐藏异常并不是一个好主意。您正在返回 null 并仅记录一个异常,而不是重新抛出它并让调用代码决定要做什么。可能适用于您的用例,但通常是一个危险信号。

    【讨论】:

    • 您使用的是哪个 .NET 版本?
    • 抱歉,调用站点出现了基于旧版本代码的错误。再试一次(注意已从 _ =&gt; ... 更改为 () =&gt; ...)。
    • 相信我,我遇到了同样的错误,它修复了那个错误。我不是指我添加的新的“.NET 2.0”cmets,而是foobar 中的调用站点更新。假设controller.barcontroller.foo 都返回Result。是吗?
    • 啊,现在可以了,我用第二个参数弄坏了它。是的,你是对的,它是 () 括号!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多