dance2die
dance2die

Reputation: 36945

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.

Upvotes: 1

Views: 1320

Answers (5)

JoshBerke
JoshBerke

Reputation: 67108

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.

Upvotes: 4

codekaizen
codekaizen

Reputation: 27429

Not possible with generics, but with C++/CLI's variadic templates (when it gets support for them), you can do it.

Upvotes: 0

Chris Dunaway
Chris Dunaway

Reputation: 11216

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

Upvotes: 0

Anton Gogolev
Anton Gogolev

Reputation: 115859

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.

Upvotes: 0

Andrew Hare
Andrew Hare

Reputation: 351616

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.

Upvotes: 5

Related Questions