1

After I asked this question and read this recommended article about closures, I have started to ask myself that if making closure in C# involves boxing.

As it said in the article , this lines of code will create a closure by making myVar exist outside it's scope :

public static Func<int,int> GetAFunc()
{
    var myVar = 1;
    Func<int, int> inc = delegate(int var1)
                            {
                                myVar = myVar + 1;
                                return var1 + myVar;
                            };
    return inc;
}

As explained there, an object of a compiler generated class is instantiated to carry the value of this variable outside it's scope. Here comes my question: Since the variable is indeed located on stack, making it part of an object, doesn't mean that closures involves boxing?

Community
  • 1
  • 1
meJustAndrew
  • 6,011
  • 8
  • 50
  • 76
  • The variable is **not** located on the stack. The C# compiler rewrites your code and *myVar* becomes a field of a class. No boxing anywhere. Use ildasm.exe to see this for yourself. – Hans Passant Jun 22 '16 at 20:36
  • There is no boxing when value type is field of another type... You may want to look again at code generated for closures. – Alexei Levenkov Jun 22 '16 at 20:36

1 Answers1

9

Since the variable is indeed located on stack, making it part of an object, doesn't mean that closures involves boxing?

The number of mistakes in that sentence is large. Let's disabuse you of some myths.

(1) Variables of value type do not "go on the stack". Variables that have short lifetimes go on the stack. Does this variable have a short lifetime? No. It has an arbitrarily long lifetime. So does it go on the stack? No.

(2) A field of an object of reference type is not on the stack. It's on the heap. Why? Because, again, a field has an arbitrarily long lifetime.

(3) An integer that is in a variable that is on the heap does not need to be boxed. Whether the integer is boxed or not depends on whether the integer has been converted to a reference type or not. The location of the variable is irrelevant; what matters is whether the type of the variable is a reference type or a value type.

So let's look at your code:

public static Func<int,int> GetAFunc()
{
    var myVar = 1;
    Func<int, int> inc = delegate(int var1)
                            {
                                myVar = myVar + 1;
                                return var1 + myVar;
                            };
    return inc;
}

This code is equivalent:

private class Closure
{ 
  public int myVar;
  public int SomeFunction (int var1)
  {
    this.myVar = this.myVar + 1;
    return var1 + this.myVar;
  }
}
public static Func<int,int> GetAFunc()
{
    Closure locals = new Closure();
    locals.myVar = 1;
    Func<int, int> inc = locals.SomeFunction;
    return inc;
}

Is there any time in there when an integer is converted to a reference type? No. So, no boxing.

HOWEVER remember, the point of avoiding boxing is avoiding the cost of allocating an extra object. We did allocate an extra object: the closure! There is no boxing penalty here, but there is a penalty due to the closure. Allocating the closure increases collection pressure. And of course, all references to the local must now go through an extra indirection.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • You are right sir! Can I ask one more question on this subject? It doesn't involves boxing because the class "Closure" it's generated at compile time, so the variable isn't first allocated on stack, then moved to heap. Have I understood right? – meJustAndrew Jun 22 '16 at 20:45
  • @meJustAndrew No. It doesn't involve boxing because a value type is never converted to a reference type. The stack/heap have absolutely nothing to do with this concept. – Chris Hannon Jun 22 '16 at 20:51
  • I had a proper understanding of boxing, it is right. I thought this happens when a value type is converted to a reference type. But about the afirmation number 1, why does value type variables does not go to stack, as I think they were, according to [this article from msdn](https://msdn.microsoft.com/ro-ro/library/4d43ts61(v=vs.90).aspx) where it says that "A value type stores its contents in memory allocated on the stack." I know this article may be out-dated, and I apreciate your answers by now, I don't want to be disrespectful by keep asking things. – meJustAndrew Jun 22 '16 at 21:27
  • 2
    @meJustAndrew That's an unfortunate article, as it makes incorrect generalizations about the stack/heap semantics. As Eric said, the storage location is related to the lifetime of the storage, not the type stored inside it. – Chris Hannon Jun 22 '16 at 21:51
  • 3
    That article is my nemesis. It has misled so many people. The notion that the stack is for value types is just silly; the stack is for *short lived storage*. If storage needs to live a long time then it has to go on the heap regardless of whether the storage contains a reference or a value! – Eric Lippert Jun 22 '16 at 23:41