Как использовать вызов метода в качестве параметра - PullRequest
1 голос
/ 11 октября 2019

Как в 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. Как это можно написать максимально гибко и просто?

1 Ответ

3 голосов
/ 11 октября 2019

Вы можете применять аргументы, когда вы создаете лямбду, которая будет синхронизироваться, а не внутри метода, который выполняет синхронизацию.

Таким образом, вы можете реализовать функцию хронирования следующим образом (используя кортеж для возврата двух значений):

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);
        }
    }
}

Этот подход аналогичен «частичному применению функции», , как обсуждалось вэта статья .

Примечание. Если вы не можете использовать кортежи, потому что используете старую версию C #, вам придется объявить метод синхронизации следующим образом:

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

    return result;
}

и соответственно измените звонки на него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...