Hazz said:
Thank you Ignacio but I guess I didn't ask my question clearly.
If the eventhandler will never handle anything other than (in this case)
comboboxes, why do I need to cast to comboboxes?
Is it because sender is of a generic object type? Does the runtime not
know that this is an object of type combobox?
If I am passing by reference rather than by value, doesn't the heap retain
the combobox info? Or is this a metadata thing?
Is that why I also often see the 'TypeOf' keyword at the beginning of a
method, to test to see if perhaps this object that is passed in as an
argument is of the type Combobox? Or is this for some other reason?
thx, -hazz
First thing, don't use the word generic to describe something general. This
will just make you confused when you move to .NET 2.0 and actually have
generic types.
As for your problem. The event handler is defined by a general delegate that
is used all over the .NET framework for simple events. Hence even though
your combobox knows its type, the delegate does not and you must resort to
downcasting.
The combobox triggers the event and sends itself as sender and in the
process it gets upcasted to Object. In order to access the the instance as
more than a Object you must downcast it to an appropriate type. If you only
need it's name you could downcast to Component and if you need it's position
you could downcast to Control. However, if you want to know it's selcected
item you need to downcast to ComboBox.
Downcasting is dangerous as you must know what type the instance can be cast
to. This is what generics will try to solve for us with parameterized types.
It's a very nifty thing to have.
..NET is not only about managed data (ie having a garbage collector) but also
managed code. Hence if you try to downcast an instance of a ComboBox from an
Object-reference into a StringBuilder the Common Language Runtime (CLR) will
check if it's an ok cast and throw a InvalidCastException if you tried.
The same is not true for unmanaged code like C++ and Delphi. If you make an
illegal cast you really screw things up and you wind up with a reference
pointing to one type of object using methods of the wrong class, typically
giving you the infamous 'General Protection Fault' or 'Access Violation'
exception when the code being called makes non sense. This is also why C++
and Delphi sport much better performance than .NET and Java. The former
don't check what we do and the latter hold our hands while we do it.
Casts in C# is actually methods, called cast operators, even though they get
very much optimized by the CIL-compiler for most types in the Common Type
System (CTS).
C# introduces two types of cast operators; implict- and explicit-casts.
Example with cast operators on System.Byte and System.Int32:
myInt = myByte; //implicit cast, a 8-bit can always become an 32-bit
myByte = (Byte)myInt; //explicit cast needed as an int may contain a large
value which throws an exception.
If you define a class in C# you can supply it with your own cast operators.
Hence a subclass called MyComboBox could very much become a StringBuilder,
if you'd want. =)
But note the smiley. You should be very careful before overloading
operators, even cast operators. Cast operators should only be used when
there is a natural and simple conversion from one type to another. Note how
a System.Byte can be cast to System.Int32 without effort and therefor
supports a cast operator for it, while making it into a string involve
actual work and so you must call the method.ToString()
Hope this made you less confused.=)
- Michael S