{"id":3115,"date":"2010-07-27T18:15:00","date_gmt":"2010-07-27T18:15:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/introduction-to-open-instance-delegates\/"},"modified":"2016-07-28T10:50:06","modified_gmt":"2016-07-28T10:50:06","slug":"introduction-to-open-instance-delegates","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/introduction-to-open-instance-delegates\/","title":{"rendered":"Introduction to open instance delegates"},"content":{"rendered":"<p>Creating a delegate to a method is normally quite a cheap operation. However, there are some reflection-based situations where you have to create a delegate dynamically using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/9tz542wy.aspx\"><code>Delegate.CreateDelegate<\/code><\/a>. As you can expect, such a method is many times slower than using the type-safe delegate constructor. Using open instance delegates can help alleviate this performance penalty.<\/p>\n<p>For this post, I&#8217;ll be using these classes in the examples: <\/p>\n<pre>delegate void AddDelegate(int value);\n\nclass Adder {\n\n    public Adder(int value) {\n        Value = value;\n    }\n    \n    public int Value { get; private set; }\n\n    public void Add(int valueToAdd) {\n        int result = Value + valueToAdd;\n        Console.WriteLine(\"{0}+{1}={2}\", Value, valueToAdd, result);\n    }\n}<\/pre>\n<\/p>\n<p><b>Creating a delegate<\/b><\/p>\n<p>The standard way of creating a delegate to an instance method is the following (I&#8217;ve expanded out the syntax for clarity): <\/p>\n<pre>Adder add5 = new Adder(5);\nAddDelegate d = new AddDelegate(add5.Add);<\/pre>\n<p>  This simply calls the compiler-created constructor on the <code>AddDelegate<\/code> type. In situations where you need to create the delegate dynamically, you need to use the <code>Delegate.CreateDelegate<\/code> methods instead: <\/p>\n<pre>Adder add5 = new Adder(5);\n\nMethodInfo addMethodInfo = typeof(Adder).GetMethod(\"Add\");\nAddDelegate d = (AddDelegate)\n    Delegate.CreateDelegate(typeof(AddDelegate), add5, addMethodInfo);<\/pre>\n<p>  In this example, in the arguments to <code>CreateDelegate<\/code>, we&#8217;re specifying the type of delegate to create, the instance of <code>Adder<\/code> the method is to be run on, and the <code>MethodInfo<\/code> of the method to run as the delegate.<\/p>\n<p><b>The hidden &#8216;this&#8217; pointer<\/b><\/p>\n<p>The reason we need to specify the <code>firstArgument<\/code> parameter to <code>CreateDelegate<\/code> is that every instance method invocation requires a reference to the object we&#8217;re calling the method on (the &#8216;this&#8217; pointer) to be the first argument it is called with, before all the declared method arguments (for <code>Add<\/code>, the <code>value<\/code> parameter). What happens if we <i>don&#8217;t<\/i> specify this argument when creating the delegate?  <\/p>\n<pre>AddDelegate d = (AddDelegate)\n    Delegate.CreateDelegate(typeof(AddDelegate), null, addMethodInfo);<\/pre>\n<p>  Not a lot it would seem; trying to invoke such a delegate throws a <code>NullReferenceException<\/code> if it&#8217;s a virtual method or accesses the &#8216;this&#8217; instance (which most instance methods do). However, things get a lot more interesting if we change the delegate signature slightly:  <\/p>\n<pre>delegate void OpenAddDelegate(Adder explicitThis, int value);\n\nOpenAddDelegate add = (OpenAddDelegate)\n    Delegate.CreateDelegate(typeof(OpenAddDelegate), null, addMethodInfo);<\/pre>\n<p> Here, we&#8217;re explicitly specifying the hidden &#8216;this&#8217; pointer of the <code>Add<\/code> method as part of the delegate signature. A delegate to an instance method created in this way is called an <i>open instance delegate<\/i>, and by specifying the &#8216;this&#8217; argument explicitly we can use this delegate instance to call the same method on multiple instances:  <\/p>\n<pre>Adder add3 = new Adder(3);\nAdder add4 = new Adder(4);\n\nMethodInfo addMethodInfo = typeof(Adder).GetMethod(\"Add\");\nOpenAddDelegate d = (OpenAddDelegate)\n    Delegate.CreateDelegate(typeof(OpenAddDelegate), null, addMethodInfo);\n\nd(add3, 2);\nd(add3, 3);\nd(add4, 5);\nd(add4, 6);<\/pre>\n<\/p>\n<p><b>So?<\/b><\/p>\n<p>Such a delegate may not seem immediately useful, but this can be crucial when performance is critical. Creating a delegate with <code>CreateDelegate<\/code> is an expensive operation, and if you have to call the same delegated method on many thousands of objects it can be a killer to create a new delegate instance for each object. To demonstrate this, I ran 3 tests that called a delegate of the <code>Add<\/code> method on 1,000,000 <code>Adder<\/code> objects, creating the using the normal delegate constructor, a closed <code>CreateDelegate<\/code> call for each object, and a single open instance delegate:<\/p>\n<pre>Delegate constructor:     0.1115875s\nClosed instance delegate: 4.6705494s\nOpen instance delegate:   0.0621132s<\/pre>\n<p>Such results speak for themselves. Although rather a niche feature, when calling the same method on many thousands of separate instances, open instance delegates can improve the performance of such code many times over.<\/p>\n<p>Note: This also works as expected for delegates to virtual and interface methods. You can also use the generic <code>Func<\/code> and <code>Action<\/code> delegates if you wish, rather than defining your own delegate type, as long as the type of the first argument of the delegate is compatible with the type containing the instance method you&#8217;re calling.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating a delegate to a method is normally quite a cheap operation. However, there are some reflection-based situations where you have to create a delegate dynamically using Delegate.CreateDelegate. As you can expect, such a method is many times slower than using the type-safe delegate constructor. Using open instance delegates can help alleviate this performance penalty&#8230;.&hellip;<\/p>\n","protected":false},"author":186659,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-3115","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/186659"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3115"}],"version-history":[{"count":1,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3115\/revisions"}],"predecessor-version":[{"id":25082,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3115\/revisions\/25082"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3115"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}