简体   繁体   中英

Can you declare a variable length Generics type declaration?

I have an overloaded utility method called CheckDuration with following function signatures.

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

Basically CheckDuration prints on console how long it took to run a method.

Now, I would like to check the duration of a method that takes 2 argument.
So I would have to create another overloaded CheckDuration with following method signature.

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

Is there a way to handle this more gracefully?
I was thinking about something like

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

, which obviously doesn't work.

[UPDATE] I will leave this question open for now to see if anyone has come up with a work-around for this kind of problem.

Unfortunately what you have already is about as clean as its going to get. C# does not support the use of params for generic type parameters and supporting something like that would be very difficult. Your original solution is good and is in the spirit of similiar delegates in the BCL like the Action delegates which have overloaded definitions to take different numbers of arguments.

You can't do it quite like you want but you can achieve the same goal:

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

You could even define this as an extension method so your code might be:

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

This method would be defined as:

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

Edit

You do not need to define any new methods this approach is using a closure around the method that you want to time. So:

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

And so on and so on.

No, there's no way. However, I suppose that for this 'CheckDuration' to work, both T and U should either implement some well-defined interface or inherit from one base class (or otherwise you'll be doing lots of reflection, which kinda defeats the purpose of using generics). Thus, consider:

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

And you'll be able to stuff anything that's ISupportCheckDuration -compatible in there.

Have a look at PostSharp:

http://www.postsharp.org/

I think it could help you. Look at the trace example. I think you could adapt it to perform your timing. Then you could just add an attribute to any method you need to time, regardless of the number of arguments it takes.

Chris

对于泛型来说是不可能的,但是对于C ++ / CLI的可变参数模板(当它获得支持时),您可以做到。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM