C# FAQ

Delegates

Q: What do delegates buy you?
A: Delegates enable scenarios that some other languages have addressed with function pointers. However, unlike function pointers, delegates are object-oriented and type-safe.

Q: Are delegates really type-safe?
Not really. A delegate instance does not know or care about the classes of the methods it encapsulates; all that matters is that those methods be compatible with the delegate's type.

Q: What does that mean?
The problem is best illustrated with an example:
   using System;

class Department {
    public delegate void Fireable();

    public static void FireEmployee(Fireable fireable) {
        fireable();
    }
}

class Military {
    public delegate void Fireable();

    public static void FireMissile(Fireable fireable) {
        fireable();
    }
}

class Missile {
    public void Fire() {
        Console.WriteLine("missile fired");
    }
}

class Employee {
    public void Fire() {
        Console.WriteLine("employee fired");
    }
}

class Test {
    static Employee e1 = new Employee();
    static Missile e2 = new Missile();

    static void Main(string[] args) {
        Department.Fireable e = new Department.Fireable(e2.Fire);
        Department.FireEmployee(e);
    }
}
In this program, the programmer has made an error. The line
           Department.Fireable e = new Department.Fireable(e2.Fire);
really should be
           Department.Fireable e = new Department.Fireable(e1.Fire);
However the compiler does not detect this coding error. The program compiles fine and you get this output when you run it:
   missile fired
Uh oh! The programmer intended to fire an employee, but he has launched a missile instead!

Q: Is there a better way to do this?
A: Yes. You can get type safety by using interfaces instead of delegates.
   using System;

class Department {
    public interface Fireable {
        void Fire();
    }
    public static void FireEmployee(Fireable fireable) {
        fireable.Fire();
    }
}

class Military {
    public interface Fireable {
        void Fire();
    }
    public static void FireMissile(Fireable fireable) {
        fireable.Fire();
    }
}

class Missile : Military.Fireable {
    public void Fire() {
        Console.WriteLine("missile fired");
    }
}

class Employee : Department.Fireable {
    public void Fire() {
        Console.WriteLine("employee fired");
    }
}

class Test {
    static Employee e1 = new Employee();
    static Missile e2 = new Missile();

    static void Main(string[] args) {
        Department.Fireable e = e1;
        Department.FireEmployee(e);
    }
}
Try changing the line
           Department.Fireable e = e1;
to this:
           Department.Fireable e = e2;
When you try to compile the program the compiler tells you:
   test.cs(38,33): error CS0029: Cannot implicitly convert type 'Missile' to
        'Department.Fireable'
The compiler has detected your coding error!

Q: What is type safety all about?
A: Type safety is about increasing the opportunities for the compiler to detect your coding errors. If you use interfaces instead of delegates the compiler will have more opportunities to detect your coding errors.

Q: What other differences exist between delegates and interfaces?
A: Interfaces carry semantics, and when a programmer implements an interface, he is typically well aware of that semantics. When you try to invoke a particular method via an interface, you can be fairly certain that if you succeed, the semantics of that method is what you expect. For that reason, using interfaces is essentially doing a check for semantic correctness on some level.

Delegates, on the other hand, by only verifying the method signature, make the programmer responsible for ensuring that the semantics of the method is compatible. The semantics may cover not only the meaning of the arguments and return value (some times even the order of the arguments if they are of the same type), the ranges of the arguments, but also an invocation order when multiple methods are concerned. Hence, in a sufficiently large program there is plenty of margin to make an error when different programmers are not forced to comply with a uniform semantics (as they would be if interfaces were used).

[credit: Mind Bridge]

Q: What can we conclude from all this?
A: Use of delegates results in shorter but less reliable code.

C# Best Practice

Prefer interfaces over delegates

[Back to Index]













1