Home |  JournalSeek |  SoftwareSeek |  GenomeSeek |  Expression |  Developer |  TakeOnIt
Return to Genamics Home

8. Structs

It is helpful to view C# structs as a construct which makes the C# type system work elegantly, rather than just "a way to write really efficient code if you need to".

In C++, both structs and classes (objects) can be allocated on the stack/in-line or on the heap. In C#, structs are always created on the stack/in-line, and classes (objects) are always created on the heap. Structs indeed allow more efficient code to be created:

public struct Vector {
    public float direction;
    public int magnitude;

Vector[] vectors = new Vector [1000];

This will allocate the space for all 1000 vectors in one lump, which is much more efficient that had we declared Vector as a class and used a for-loop to instantiate 1000 individual vectors. What we've effectively done is declared the array like we would declare an int array in C# or Java:

int[] ints = new ints [1000];

C# simply allows you to extend the primitive set of types built in to the language. In fact, C# implements all the primitive types as structs. The int type merely aliases System.Int32 struct, the long type aliases System.Int64 struct etc. These primitive types are of course able to be treated specially by the compiler, but the language itself does not make such a distinction. The next section shows how C# takes advantage of this.

9. Type Unification

Most languages have primitive types (int, long, etc), and higher level types which are ultimately composed of primitive types. It is often useful to be able to treat primitive types and higher level types in the same way. For instance, it is useful to have collections which can take both ints as well as strings. Smalltalk achieves this by sacrificing some efficiency and treating ints and longs as types like String or Form. Java tries to avoid sacrificing this efficiency, and treats primitive types like in C or C++, but provides corresponding wrapper classes for each primitive - int is wrapped by Integer, double is wrapped by Double. C++'s templates allow code to be written which takes any type, so long as the operations done on that type are provided by that type.

C# provides a different solution to this problem. In the previous section, I introduced C# structs, explaining how primitive types like int were merely aliases for structs. This allows code like this to be written, since structs have all the methods that the object class does:

int i = 5;
System.Console.WriteLine (i.ToString());

If we want to use a struct as an object, C# will box the struct in an object for you, and unbox the struct when you need it again:

Stack stack = new Stack ();
stack.Push (i); // box the int
int j = (int) stack.Pop(); // unbox the int

Apart from a type-cast required when unboxing structs, this is a seamless way to handle the relationship between structs and classes. You should bare in mind that boxing does entail the creation of a wrapper object, though the CLR may provide additional optimization for boxed objects.

The designers of C# must have considered templates during their design process. I suspect there were two main reasons for not using templates. The first is messiness - templates can be difficult to mesh with object oriented features, they open up too many (confusing) design possibilities for programmers, and they are difficult to work with reflection. The second is that templates wouldn't be very useful unless the .NET libraries like the collection classes used them. However, if the .NET classes used them, then the 20+ languages which use the .NET classes would have to work with templates too, which may be technically very difficult to achieve.

It is interesting to note that templates (generics) are being considered for inclusion in the Java language by the Java Community Process. It may be that each company starts singing each other's tunes when Sun says that ".NET suffers from lowest common denominator syndrome", and Microsoft says "Java doesn't have cross-language support".

(Amended 10 August) From reading an interview with Anders Hejlsberg, it appears templates are on the horizon, but not for the first release, for the difficulties which were suggested above. It was very interesting to see that the IL specification was written so that the IL code could represent templates (in a non-destructive way so that reflection works well), while byte-code was not. I've also included a link to the Java Community Process for considering generics in java:

Previous     Next

C# 3.0 in a Nutshell (April 2007) - by Joseph Albahari and Ben Albahari.

Add To Favorites
Email This Page

Side Panel
Privacy Policy About Us Contact Us