Boxing
It is possible to convert from a value type to a reference type, and vice versa, via boxing. Take this C# example:
~~~~~~~~~~~~~~~~~~~~~~~~~
object obj = null; // a reference type
int i = 5; // a value type
obj = i; // boxing
//i = obj; // compiler error
i = (int)obj; // unboxing: the value type is copied to i
~~~~~~~~~~~~~~~~~~~~~~~~~
On the third line, the value type is implicitly boxed to a reference type. In C#, you cannot assign an object type to value type, so the fourth line is a compiler error. You must explicitly cast to the value type, which copies the data at that time.
Note that Delphi is very type safe, so consider the analogous Delphi .NET code:
~~~~~~~~~~~~~~~~~~~~~~~~~
var
I: Integer;
Obj: TObject;
begin
I := 5;
Obj := I; // Compiler error: Incompatible types
// I := Obj; // Expected compiler error
I := Integer(Obj) ;
end.
~~~~~~~~~~~~~~~~~~~~~~~~~
The above code will not compile on the second line of code due to Delphi being very type safe. In this case, the programmer can do one of two things; explicitly cast I to a TObject:
Obj := TObject(I) ;
Or, add the compiler AUTOBOX directive any where in the source before the line:
{$AUTOBOX ON}
The AUTOBOX directive makes Delphi less type safe, and more like C#. Using it can add ease of use, and can also lead to more programming errors.
System.Delegate and System.EventHandler
The FCL provides delegates as a managed means for method pointers, which can be used as event handlers or callback functions in the .NET Framework. The basic implementation of System.Delegate allows one to add and subtract to a delegate, and call the methods contained in it.System.Delegate is the base class for all delegates. System.MulticastDelegate descends from System.Delegate and adds the ability to call multiple methods. If a delegate is non-multicast, it can contain a reference to only one method.
Declaring a Custom Delegate Type
Any .NET compiler should take care of delegate creation via a keyword or specific syntax. C# uses the delegate keyword:
~~~~~~~~~~~~~~~~~~~~~~~~~
public delegate void SampleEventHandler(object sender, EventArgs args) ;
~~~~~~~~~~~~~~~~~~~~~~~~~
First off, notice that the delegate's name ends with EventHandler. This is very common, and Microsoft recommends naming all delegates in this format for consistency; however, doing so is not required.
Also notice that the delegates method signature has a void return type, a first parameter of type object, and a second parameter of type EventArgs. This method signature is very common in the FCL, and is the Microsoft recommended format, but one is not required to use it. However, it is so common, that this event signature has its own delegate, System.EventHandler. By convention, the first parameter is always the instance who invoked the method. The second parameter contains arguments describing the event.
If you want to pass more information to delegate, you can descend from EventArgs and add the necessary properties in your custom EventArgs class:
~~~~~~~~~~~~~~~~~~~~~~~~~
public class MyEventArgs : EventArgs
{
public MyEventArgs(string mySpecialValue)
{
MySpecialValue = mySpecialValue;
}
public string MySpecialValue;
}
public delegate void SampleSpecialEventHandler(object sender, MyEventArgs args) ;
~~~~~~~~~~~~~~~~~~~~~~~~~
When the delegate is then called, the callee can access args.MySpecialValue.
Declaring a custom delegate type in Delphi is very easy and familiar; you just make a standard method type declaration:
type
TSampleEventHandler = procedure(Sender: TObject; Args: EventArgs) ;
Let's now see how to create and use a delegate instance...

