6/4/2005 9:14:10 PM


A blogger (can’t find his link anymore) just recently pointed out a leaky abstraction in .NET, that pointers are the only types in .NET that can’t be cast to object. In other words, pointers cannot be boxed.

It’s true that, in C#, pointers cannot be boxed. It’s probably true that they cannot be boxed directly in IL either, but it is not entirely clear to me from the IL specification. The specification states that box only works on valuetypes.

However, not CLS compliant, pointers do need to work in Reflection, and the framework does provide a mechanism to box pointers through the System.Reflection.Pointer class, which is derived from System.Object. The Pointer class contains static members Box(void *p, Type type) and Unbox(void *p).

With the Pointer type, C# perhaps could have provided support for boxing. On the other hand, the type given by typeof(p), where p is a pointer, is a specially constructed pointer type, distinct from the Pointer type, with no base type (meaning it does not derive from object).

Typed Reference

There is at least one other type that cannot be cast to object, and that is the TypedReference type. This type will report that it derives from ValueType, and transitively, from Object, but it’s impossible to cast an instance of that type to either type for the very reason that its only allowable usage is in the stack and it cannot even be embedded within another structure.

TypedReference is essentially one of two managed pointer types supported in IL and maintains both the pointer value and the type of the value pointed to. In C#, there are two undocumented keywords to work with typed references, __makeref(var) for getting a typed reference to a variable and __refvalue(typeref, type) which returns an l-value that can be used for getting or setting the value of the referenced variable.

I think that the rationale for its existence is to allow members of value types to be accessed without boxing and also to be changed through Reflection. TypedReferences circumvent the boxing that would naturally occur with reflection. It’s used by FieldInfo.GetValueDirect and SetValueDirect. Calling methods and properties, however, can only be performed on boxed versions of value types.

I discovered some special uses of typed references in generics to coerce a type T into a value type without incurring boxing.


I liked to point out another coming misperception in C#. Just because C# doesn’t support a keyword for a type doesn’t mean that the runtime doesn’t handle it natively. IntPtr, for instance, is optimally handled by the runtime, so it doesn’t have the same performance hit as other valuetypes. Conversely, the decimal type does not have any performance benefits just because it’s a supported keyword.







Net Undocumented is a blog about the internals of .NET including Xamarin implementations. Other topics include managed and web languages (C#, C++, Javascript), computer science theory, software engineering and software entrepreneurship.

Social Media