|Casting – the escape from strong typing|
Page 5 of 5
You can write methods that will be called when a cast is performed to your class. However you can’t define a custom cast to or from the base class. In fact apart from making conversions to and from value types it is difficult to see what sort of custom casts you could possibly create. For example, if you want to allow ClassB to be custom cast to an int you might add something like:
public int Value=123;
This simply returns the value stored in a class variable but in practice you could return something more complicated. All cast operators have be delcared static but you can choose between explicit and implicit for the style of the cast. Following this definition you can write code like:
ClassB MyB=new ClassB();
There is the argument that if you want to do a custom type conversion like this then it would be clearer to define a ToInt method rather than a custom cast – but you can decide which suits your approach.
The cast system
Now that we have looked in detail at casting you can begin to see what it is really all about. Casting is really to do with introducing a little organised freedom into the type system so that object-oriented programming is more flexible. That is, the primary purpose of a cast is to change the type of an object not to change its representation. Without this facility there are a lot of things that would be much more difficult to do.
It is arguable that casting really shouldn’t be involved in an active type conversion because it confuses the issue. If you want to be “pure” it might be better to implement all active type conversion as a method.
To demonstrate how confusing this can be consider the following example where an object reference is downcast to an int (this is also an example of explicit boxing):
To convert back to an int (or to unbox the int) all you have to use is a simple cast:
int MyIntB = (int)MyAnything;
This works but what about:
long MyLong = (long) MyAnything;
This looks as if it is the same sort of cast but it doesn’t work because its attempting two sorts of type conversion in one go. You can’t downcast MyAnything to an int and perform the active widening conversion needed to go from an int to a long in one go.The reason is that the boxed int can only be unboxed to an int and not to another type.
The correct way to do it is the rather ugly looking:
long MyLong = (long) (int) MyAnything;
First the explicit downcast/unboxing and then the explicit widening cast are needed to make it all work.
When you realise how confused the use of casting is in C# and most modern languages you can’t help but be unhappy about it. If you want to put some order into your use of casting then only use it for passive type conversions and use a method for any active type conversion that involves any manipulation of the representation of a type.
There are various topics that we haven’t touched on that are relevant to casting. Keep in mind that generics provide a good way of avoiding the use of casts but that there are times when casting provides a more powerful solution to the same problem. Also if your real purpose is to provide active type conversion for your classes then see theTypeConverter class and the IConvertible interface in the C# documentation.
More Deep C#