Можете ли вы объявить объявление типа Generics переменной длины? - PullRequest
0 голосов
/ 28 апреля 2009

У меня есть перегруженный служебный метод с именем CheckDuration со следующими сигнатурами функций.

    private static Action<int> CheckDuration(Action action)
    private static Action<int> CheckDuration<T>(Action<T> action, T arg)

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

Теперь я хотел бы проверить продолжительность метода, который принимает 2 аргумента.
Поэтому мне пришлось бы создать еще один перегруженный CheckDuration со следующей сигнатурой метода.

    private static Action<int> CheckDuration<T, U>(
        Action<T, U> action, T arg1, U arg2)

Есть ли способ справиться с этим более изящно?
Я думал о чем-то вроде

    private static Action<int> CheckDuration<params T>(
      Action<params T> action, params T arg)

, что явно не работает.

[ОБНОВЛЕНИЕ] Я пока оставлю этот вопрос открытым, чтобы посмотреть, придумал ли кто-нибудь обходной путь для такого рода проблем.

Ответы [ 5 ]

5 голосов
/ 28 апреля 2009

К сожалению, то, что у вас уже есть, примерно так же чисто, как и собирается его получить. C # не поддерживает использование params для параметров универсального типа, и поддержка чего-то подобного была бы очень сложной. Ваше оригинальное решение хорошо и соответствует духу делегатов BCL, подобных делегатам Action, которые перегружены определениями, чтобы принимать разное количество аргументов.

3 голосов
/ 28 апреля 2009

Вы не можете сделать это так, как хотите, но можете достичь той же цели:

public static class MethodTimer
{
    public static long Run(Action action)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        action();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }
}
class Program
{
    static void Main(string[] args)
    {
        long time = MethodTimer.Run(() => File.Open(@"c:\test.txt", 
            FileMode.CreateNew));
        Console.WriteLine(time);
        Console.ReadLine();
    }
}

Вы можете даже определить это как метод расширения, чтобы ваш код мог быть:

        Action act = () => File.Open(@"c:\test.txt", FileMode.CreateNew);
        time=act.Time();

Этот метод будет определен как:

public static class MethodTimer
    {
        public static long Time(this Action action)
        {
            var sw = System.Diagnostics.Stopwatch.StartNew();
            action();
            sw.Stop();
            return sw.ElapsedMilliseconds;
        }
    }

Редактировать

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

MethodTimer.Time(()=> File.Open("",FileMode.Open);
MethodTimer.Time(()=> myObject.TestMethod(123,1231,"another param"));

И так далее, и тому подобное.

0 голосов
/ 28 апреля 2009

Невозможно с универсальными шаблонами, но с помощью вариабельных шаблонов C ++ / CLI (когда он получает их поддержку) вы можете сделать это.

0 голосов
/ 28 апреля 2009

Посмотрите на PostSharp:

http://www.postsharp.org/

Я думаю, что это может помочь тебе. Посмотрите на пример трассировки. Я думаю, что вы могли бы адаптировать его для выполнения вашего времени. Затем вы можете просто добавить атрибут к любому методу, который вам нужен, независимо от количества аргументов, которые он принимает.

Chris

0 голосов
/ 28 апреля 2009

Нет, нет пути. Тем не менее, я полагаю, что для того, чтобы этот CheckDuration заработал, T и U должны либо реализовывать некоторый четко определенный интерфейс, либо наследоваться от одного базового класса (или в противном случае вы будете много размышлять, что в некоторой степени поражает цель использования дженериков). Итак, рассмотрим:

Action<int> CheckDuration<T>(Action<T> action, params T[] args)
    where T : ISupportCheckDuration

И вы сможете добавить туда все, что ISupportCheckDuration -совместимо.

...