Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy are delegates reference types?
    primarykey
    data
    text
    <p><strong>Quick note on the accepted answer</strong>: I disagree with a small part of <a href="https://stackoverflow.com/questions/7905962/why-are-delegates-reference-types/7906297#7906297">Jeffrey's answer</a>, namely the point that since <code>Delegate</code> had to be a reference type, it follows that all delegates are reference types. (It simply isn't true that a multi-level inheritance chain rules out value types; all enum types, for example, inherit from <code>System.Enum</code>, which in turn inherits from <code>System.ValueType</code>, which inherits from <code>System.Object</code>, <em>all</em> reference types.) However I think the fact that, fundamentally, all delegates in fact inherit not just from <code>Delegate</code> but from <code>MulticastDelegate</code> is the critical realization here. As <a href="https://stackoverflow.com/questions/7905962/why-are-delegates-reference-types/7906788#7906788">Raymond points out</a> in a comment to <em>his</em> answer, once you've committed to supporting multiple subscribers, there's really no point in <em>not</em> using a reference type for the delegate itself, given the need for an array somewhere.</p> <hr> <p><strong>See update at bottom.</strong></p> <p>It has always seemed strange to me that if I do this:</p> <pre><code>Action foo = obj.Foo; </code></pre> <p>I am creating a <em>new</em> <code>Action</code> object, every time. I'm sure the cost is minimal, but it involves allocation of memory to later be garbage collected.</p> <p>Given that delegates are inherently <em>themselves</em> immutable, I wonder why they couldn't be value types? Then a line of code like the one above would incur nothing more than a simple assignment to a memory address on the stack*.</p> <p>Even considering anonymous functions, it seems (to <em>me</em>) this would work. Consider the following simple example.</p> <pre><code>Action foo = () =&gt; { obj.Foo(); }; </code></pre> <p>In this case <code>foo</code> does constitute a <em>closure</em>, yes. And in many cases, I imagine this does require an actual reference type (such as when local variables are closed over and are modified within the closure). <strike>But in some cases, it shouldn't. For instance in the above case, it seems that a type to support the closure could look like this:</strike> <strong>I take back my original point about this. The below really does need to be a reference type (or: it doesn't <em>need</em> to be, but if it's a <code>struct</code> it's just going to get boxed anyway). So, disregard the below code example. I leave it only to provide context for answers the specfically mention it.</strong></p> <pre><code>struct CompilerGenerated { Obj obj; public CompilerGenerated(Obj obj) { this.obj = obj; } public void CallFoo() { obj.Foo(); } } // ...elsewhere... // This would not require any long-term memory allocation // if Action were a value type, since CompilerGenerated // is also a value type. Action foo = new CompilerGenerated(obj).CallFoo; </code></pre> <p>Does this question make sense? As I see it, there are two possible explanations:</p> <ul> <li>Implementing delegates properly as value types would have required additional work/complexity, since support for things like closures that <em>do</em> modify values of local variables would have required compiler-generated reference types anyway.</li> <li>There are some <em>other</em> reasons why, under the hood, delegates simply <em>can't</em> be implemented as value types.</li> </ul> <p>In the end, I'm not losing any sleep over this; it's just something I've been curious about for a little while.</p> <hr> <p><strong>Update</strong>: In response to Ani's comment, I see why the <code>CompilerGenerated</code> type in my above example might as well be a reference type, since if a delegate is going to comprise a function pointer and an object pointer it'll need a reference type anyway (at least for anonymous functions using closures, since even if you introduced an additional generic type parameter—e.g., <code>Action&lt;TCaller&gt;</code>—this wouldn't cover types that can't be named!). <strong>However</strong>, all this does is kind of make me regret bringing the question of compiler-generated types for closures into the discussion at all! My main question is about <em>delegates</em>, i.e., the thing <em>with</em> the function pointer and the object pointer. It still seems to me <em>that</em> could be a value type.</p> <p>In other words, even if this...</p> <pre><code>Action foo = () =&gt; { obj.Foo(); }; </code></pre> <p>...requires the creation of <strong>one</strong> reference type object (to support the closure, and give the delegate something to reference), why does it require the creation of <strong>two</strong> (the closure-supporting object <em>plus</em> the <code>Action</code> delegate)?</p> <p><sub>*Yes, yes, implementation detail, I know! All I really mean is <em>short-term memory storage</em>.</sub></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload