The Daily Parker

Politics, Weather, Photography, and the Dog

T is for Type

Blogging A to ZNow that I've caught up, day 20 of the Blogging A-to-Z challenge is just a few hours late. (The rest of the week should be back to noon UTC/7 am Chicago time.)

Today's topic: Types.

Everything in .NET is a type, even System.Type, which governs their metadata. Types exist in a hierarchy called the Common Type System (CTS). Distilled, there are two kinds of types: value types and reference types. I alluded to this distinction Saturday earlier today when discussing strings, which are reference types (classes) that behave a lot like value types (structs).

The principal distinction is that value types live on the stack and reference types live on the heap. This means that all of the data in a value type is contained in one place. The CLR sets aside memory for the entire object and moves the whole thing around as a unit. Naturally, this means value types tend to be small: numbers, characters, booleans, that sort of thing.

Reference types also partially live on the stack but only as a pointer to the heap where they keep their main data. The .NET memory manager can move reference types and their data independently as needed to handle different situations.

One of the consequences of this distinction is that when you pass a value type to a method, you're passing the entire thing; but when you pass a reference type to a method, you're only passing its pointer. This can give new .NET developers terrific headaches:

public void ChangeStuff()
{
	var i = 12345; // i is a System.Int32
	var p = new MyClass { Name = "Hubert", Count = i };
	
	ChangeStuff(i, p);
	
	Debug.Assert(12345 == i); // Succeeds!
	Debug.Assert(54321 == MyClass.Count); // Succeeds!
	Debug.Assert("Hubert" == MyClass.Name); // Fails!
}

private void ChangeStuff(int i, MyClass myClass)
{
	i = 54321; // The i in this method is not the i in the calling method
	MyClass.Name = "Humbert"; // But the MyClass is
	MyClass.Count = i;
}

When the CLR passes i to the second ChangeStuff method, it creates a copy of i on the stack and passes in that copy. Then on line 15, we create a third copy of i that replaces the second copy on the stack.

But lines 16 and 17 aren't creating copies of MyClass; they're using the pointer to the instance of MyClass created on line 4, so that any operations on MyClass work on the very same instance.

I recommend new developers read the MSDN article on Types I referenced above. Also read up on boxing and unboxing and anonymous types.

Comments (1) -

  • Jacqui Murray

    4/23/2018 5:00:11 PM +00:00 |

    That actually was quite helpful.

Comments are closed