2

This question is more out of curiosity than a real problem. Consider the following code (C# 4.0, if it matters):

class Program {
  static Point myPoint = new Point(3, 5);

  static void Main(string[] args) {
    Console.WriteLine("Point Struct Before: " + myPoint);
    object point = GetPoint();
    Console.WriteLine("Point Object Before: " + point);
    myPoint.X = 10;
    Console.WriteLine("Point Struct After: " + myPoint);
    Console.WriteLine("Point Object After: " + point);
  }

  static object GetPoint() {
    return myPoint;
  }
}

This outputs the following:

Point Struct Before: 3;5
Point Object Before: 3;5
Point Struct After: 10;5
Point Object After: 3;5

Now, this works as it should, meaning the point returned by GetPoint() is being copied rather than referenced. (Otherwise the last line would also have read "10;5".)

My question now is: Why does this work? How does the compiler know whether to copy or reference an object? Does this mean that this decision is done during runtime rather than during compilation?

Also, this now allows me to set point to null whereas structs can't be set to null. Is the struct automatically converted into a nullable type?

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Sebastian Krysmanski
  • 8,114
  • 10
  • 49
  • 91

4 Answers4

8

Also, this now allows me to set point to null whereas structs can't be set to null. Is the struct automatically converted into a nullable type?

You are misunderstanding the whole process:

int i = 5;
object o = i; //Creates a new Int32 with value 5 and assigns it to the object'o' reference storing the value on the garbage collected heap. This is what is called boxing.
object o = null //Simply assigns 'null' to the object reference, it does nothing to the boxed value type 'o' was referencing before.

In the example above the boxed int will eventually be collected by the GC from the garbage collected heap as no live reference is pointing at it anymore.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • The problem with Int32 (as well as any other boxing type) is that they're all value types as well. So you still would assign a value type to a reference type. – Sebastian Krysmanski Jun 10 '11 at 10:30
  • @Sebastian I know this is late, but `ValueType` still inherits from `object` so it's perfectly legal to assign a value type to `object`. It's the other way around that's a problem. – Davy8 Jun 15 '11 at 22:06
4

You are observing the process called boxing. It essentially converts a value type into a reference type.

Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
Zruty
  • 8,377
  • 1
  • 25
  • 31
4

You are not converting myPoint to an object, you are just creating a copy of the myPoint structure (through the GetPoint method) and assigning an object reference to it.

Johann Blais
  • 9,389
  • 6
  • 45
  • 65
3

Although Microsoft in some sense claims that all types derive from object, it's more helpful to regard value types as being things which are totally outside the type system, but which have boxed equivalents within the typing system (all of which derive from ValueType), along with widening conversion operators between them and the boxed equivalents. If one passes an a structure to a routine which expects an Object, one isn't really passing a value type, but rather the boxed equivalent of a value type. If that is passed around to other routines that expect Object, they will continue to use the same boxed object. If it is passed to routines that expect the structure, it will be converted back to a structure for use with those routines. Note that each time it's converted, a snapshot is taken of the value; changes to the snapshot will not affect the copied entity, nor vice versa.

supercat
  • 77,689
  • 9
  • 166
  • 211