Charles Petzold

.NET Classes vs. Structures

May 13, 2007
New York, N.Y.

At Devscovery NYC this past week I heard somebody say that you should always define new .NET types as classes rather than structures to avoid boxing problems. (Boxing is when a value type has to be cast to object, usually to be passed to a method defined with an object argument. Boxing and unboxing are time-consuming operations and can often not be very obvious.)

I disagree about using classes exclusively. Consider the following code:

If Stuff is a structure, then you've just allocated an array filled with 1000 Stuff instances, and each of the instances has been initialized to zero.

If Stuff is a class, then you've just allocated an array sufficient to hold 1000 references, each of which has been initialized to null. Eventually, when your array is full, you'll be dealing with 1001 heap allocations, compared to just one if Stuff is a structure.

Any type that requires a fairly small amount of storage and has the prospect of being the basis of a large array should be defined as a structure rather than a class. The Point structure is an obvious example.

I've recently become very attuned to writing efficient PropertyChangedCallback routines for dependency properties. By default, dependency properties are animatable, which means that the PropertyChangedCallback could be called some 60 or more times per second for a very long period of time. It's a good idea for this callback not to make any routine heap allocations, which might cause the garbage collector to interrupt your animations. In some cases, I've stored pre-allocated classes as fields for use in the callback, but it's always a pleasure when you need a new Point or Point3D or other value type and you don't need to worry about heap allocations.

(By the way, if you really can't avoid a lot of memory allocations in a PropertyChangedCallback, you might want to flag the dependency property as non-animatable. You can do this using a UIPropertyMetadata object and setting the IsAnimationProhibited flag to true.)

The distinction between classes and structures in .NET is a very important one. While most new types should be classes, it's always good to consider the issues and know why you're making that decision.

And of course, if you do decide to go with a structure, you should avoid boxing. That means writing overloads of your own methods to accept the specific structures you define rather than just object. When calling Console.WriteLine or String.Format, don't pass the object; pass the object dot ToString. Other more nefarious methods might involve more ingenious solutions.