Can you create an instance method delegate without specifying an instance at creation time? In other words, is it possible to create a “static” delegate that accepts the instance on which the method should be called as the first parameter?
For example, how can I build the next delegate using reflection?
Func<int, string> = i=>i.ToString();
I know that I can use methodInfo.Invoke, but it is slower and does not check the correctness of the text until it is called.
When you have a MethodInfo
specific static method, you can build a delegate using Delegate.CreateDelegate(delegateType, methodInfo)
, and all the parameters of the static method remain free.
As John Skeet pointed out, you can simply apply the same to make an instance method public delegate if the method is not virtual in the reference type. The decision about which method to call using the virtual method is difficult, so it’s not so trivial, and the types of values look like they don’t work at all.
For value types, CreateDelegate
exhibits a really strange behavior:
var func37 = (Func<CultureInfo,string>)(37.ToString); var toStringMethod = typeof(int).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, new Type[] {typeof(CultureInfo) }, null); var func42 = (Func<CultureInfo,string>)Delegate.CreateDelegate(typeof(Func<CultureInfo,string>), 42, toStringMethod,true); Console.WriteLine( object.ReferenceEquals(func37.Method,func42.Method));
Call CreateDelegate
with null
because the target throws a bind exception if the instance method belonged to a value type (this works for reference types).
The next few years: an incorrectly bound target that caused func42(CultureInfo.InvariantCulture);
to return "-201040128"
instead of "42"
, in my example there was a memory corruption that could allow remote code execution ( cve-2010-1898 ); this was fixed in 2010 in security update ms10-060 . The current frames correctly print 42! This does not facilitate the answer to this question, but explains the particularly strange behavior in this example.