I'm trying to get the following thing done:
public delegate void SomeMethod(params object[] parameters);
That's my delegate. And i have some method that will run this SomeMethod delegate (whatever's passed) and return me the timespan of execution.
public TimeSpan BenchmarkMethod(SomeMethod someMethod, params object[] parameters)
{
DateTime benchmarkStart = DateTime.Now;
someMethod(parameters);
DateTime benchmarkFinish = DateTime.Now;
return benchmarkFinish - benchmarkStart;
}
Also i have some method:
public abstract void InsertObjects (Company c);
So, i declare it:
SomeMethod dlg = new SomeMethod(InsertObjects);
TimeSpan executionTime = BenchmarkMethod(dlg, c);
But it doesn't run, saying that No overload for 'InsertObjects' matches delegate 'TestFactory.MeasuringFactory.SomeMethod'. Is there any way to do it?.. Or i should change all the methods of mine to accept params object[] as an argument?..
Strictly no, the method signature must exactly match the signature specified by the delegate (except for covariant matching). However, you can create an
object[]
array and feed toDelegate.DynamicInvoke(object[] args)
.Edit:
If you have information about the method to be called, you can use
MethodBase.GetParameters().Length
to obtain the number of arguments, so you can correctly size the untyped argument array.For benchmarking, though, I think you are better off using an abstract base class that implements the necessary benchmarking ops:
Virtual method dispatches have comparable latency to delegates, and much better than dynamic invocation.
No. They still have to respect type variance.
params is only syntatic sugar for saying that from that point and beyond, all parameters of the call site are considered to be part of the same array on the method.
So, for a method defined as:
You can do:
but not:
Because, although company3 contains a Company at runtime, it's static type is object.
So now we know that params simply defines an array on a method, that allows you to use a more convenient syntax at the call site.
Now let's go on with the real reason for your code not working as you expected: Type variance
Your delegate is defined as:
and you target method as:
When invoking the delegate:
You are essentialy saying you can call InsertObjects passing it an array with any type of object instead of an object of type Company.
That of course is not allowed by the compiler.
If instead, you invert the types of the delegate and the target method such as in:
Then it will compile, because you'll be passing an array of Customer to a method that accepts any kind of object.
Conclusion: params does not affect type variance rules.
Matching
params
parameters is compiler magic, and no such magic exists for delegates. It will match a method that has an array of a compatible type in the right position, but nothing else.So yes, you need to either change all your methods, or use anonymous methods as wrappers, like this: