Reputation: 36945
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
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
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
Reputation: 11216
Have a look at PostSharp:
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
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
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