【问题标题】:How to use a method call as parameter如何使用方法调用作为参数
【发布时间】:2019-10-11 11:54:49
【问题描述】:

在C#中,如何将一个方法作为另一个方法的参数传递,通过将参数与被调用的方法一起传递,以便在内部调用该方法,例如,目标是测量其执行情况?

代码可以接近下面的伪代码吗?

public TR MeasureExecutionTime<T1, T2, T3, T4, T5, T6, TR>(this Func<T1, T2, T3, T4, T5, T6, TR> func, out long executionTime)
{
    Stopwatch stopwatch = Stopwatch.StartNew();

    TR tr = func();

    stopwatch.Stop();

    executionTime = stopwatch.ElapsedMilliseconds;

    return tr;
}

...

var result = MeasureExecutionTime(() => obj.Process(p1, p2, p3, p4, p5, p6), out long executionTime);

这里的主要问题似乎是如何传递和推导被调用者参数p1,p2,p3,p4,p5,p6。这怎么能写得尽可能灵活和简单?

【问题讨论】:

    标签: c# .net lambda delegates


    【解决方案1】:

    您可以在创建要计时的 lambda 时应用参数,而不是在执行计时的方法内。

    所以你可以像这样实现定时函数(使用一个元组返回两个值):

    public static (TimeSpan duration, T result) TimeFunction<T>(Func<T> func)
    {
        var sw = Stopwatch.StartNew();
        var result = func();
        return (sw.Elapsed, result);
    }
    

    您可以使用它来为具有多个参数的函数计时,如下所示:

    using System;
    using System.Diagnostics;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class Program
        {
            public static void Main()
            {
                // Note how we apply the parameters here, even though the 
                // function is actually called inside TimeFunction().
    
                var result = TimeFunction(() => functionToTime(1, 2.0, "3"));
    
                Console.WriteLine("Result = "   + result.value);
                Console.WriteLine("Duration = " + result.duration);
            }
    
            static string functionToTime(int intVal, double doubleVal, string stringVal)
            {
                Thread.Sleep(250);
                return $"intVal = {intVal}, doubleVal = {doubleVal}, stringVal = {stringVal}";
            }
    
            public static (TimeSpan duration, T value) TimeFunction<T>(Func<T> func)
            {
                var sw = Stopwatch.StartNew();
                var result = func();
                return (sw.Elapsed, result);
            }
        }
    }
    

    这种方式类似于“部分函数应用”,as discussed in this article

    注意:如果因为使用的是旧版本的 C# 而不能使用元组,则必须像这样声明计时方法:

    public static T TimeFunction<T>(Func<T> func, out TimeSpan duration)
    {
        var sw = Stopwatch.StartNew();
        var result = func();
        duration = sw.Elapsed;
    
        return result;
    }
    

    并相应地更改对它的调用。

    【讨论】:

    • 确实,我使用的是旧的 C# 版本,所以我只能使用第二种语法。现在,我明白了为什么我的尝试没有奏效。谢谢!
    猜你喜欢
    • 2021-10-23
    • 1970-01-01
    • 2021-05-05
    • 2013-11-30
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多