Makes perfect sense. Thanks for the explanation -- I'm not sure why I couldn't "wrap my brain around it" myself but perhaps I can blame it on my background in Java. I just need to get accustomed to thinking of quasi-objects (value types) that live on the stack - exactly as Java primitives do - but that can also be copied to the heap when necessary.
I guess my only open question is: why is there no facility provided to explicitly "box" a struct for those situations in which you do not care about the performance hit? I suppose that this would require two new language constructs -- one to indicate that a value type variable points to a "boxed" value type, and one to indicate that you would like to construct a value type on the heap rather than the stack. Such as, DateTime* dt = new* DateTime(); ...Or something like that. Of course, this just adds (perhaps unneeded) complexity to the language, so in the interim, I will go the workaround route. :) Thanks again, joe -----Original Message----- From: Craig Andera [mailto:[EMAIL PROTECTED]] Sent: Sunday, June 09, 2002 5:36 PM To: [EMAIL PROTECTED] Subject: Re: [ADVANCED-DOTNET] Value type references (versus object refere nces) > I appreciate the advantages that value types bring to the table, but I > am still missing the reason why references to value types cannot hold > NULL. Yeah, it's a bit confusing until you wrap your brain around it. Let's consider just the case of local variables for a moment, since it makes things easier to talk about. Here's the deal: a variables is just a named location on the stack. When you say int i; All you're doing is saying, "make a space on the stack called i". This space will hold an int. IT WILL HOLD THE INT ITSELF, not a reference to some place on the heap where an int lives. Similarly, when you say, Object o; All you're doing is saying "make me a space on the stack called o". This space will hold A REFERENCE TO AN OBJECT. Not the object itself, but some info (a pointer) that tells the system where to find the object. It's obvious what to put in that stack slot called "o" if you want a null reference to some object - store a value you *know* can never refer to a valid object. This is probably zero, but the JIT compiler could choose anything it wanted to, really. Now, if I wanted to store the "null int", what could I possibly store in the stack spot called i? I can't store zero, because that's also a valid *value* for i. In fact I can't store anything, because all 32 bits of the range of that sucker are completely valid values for an int. > A very similar problem is encountered when dealing with Java > primitives; however, Java provides the primitive wrapper classes that > take care of instances in which I want to store a NULL value or take > advantage of polymorphism and features reliant on Object derivations. Yeah, we actually have pretty much the same thing in .NET. When you say Object o = i; You have to think about what happens. Clearly, we're not copying the value of i (say 42) into the stack location o. That would result in a reference that pointed to some crazy and almost certainly invalid location. Plus, imagine the following (equally legal) code: struct SPoint { int x; int y; } SPoint s; Object o = s; All structs in C# are value types, so we know that the location on the stack called 's' holds the VALUE of an SPoint; that is, an x and a y. Which is 64 bits worth of goo. Now, is there any way to store 64 bits worth of goo in a variable of type object, which is probably represented as 32 bits of stack space? No. In this case, we box. Which simply means, "Make a copy of this value onto the heap, and return me a reference to it." Bingo! Now we have something - a REFERENCE to a boxed value - that fits into a variable of type Object. I suspect you already knew a large amount of this, but I think the subtle distinction between variable and instance might have escaped you. Does this help? You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com. You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com.
