An interface can be considered as a functional definition (or contract). In the real world, many objects have well-known interfaces that make them largely (but not completely) interchangeable.
For example, take a car. Once you learn how to drive a car, you will learn the “Car Driving Interface”. You know that there will be an Accelerate () function and a Stop () function and, as a rule, the ShiftGears () function (even if it just takes it out of the park and sends it to disk). There is also a Steer () function and a SignalTurn () function.
There is no guarantee that any given implementation will do the same. For example, Toyota may have a Stop () method in the CarDriving interface, which actually calls Accelerate ().
The car can support additional locks, such as the SeatBelt interface or the radio interface. Although each implementation of these objects may differ, there is always a basic set of functions that is common to all types of these objects. This allows them to be used interchangeably to a large extent without having to relearn another interface.
Interfaces in C # are similar. Different implementations of objects may contain the same implementation of an interface, and what they do may be different, but you can consider one object that implements a particular interface in the same way you handle another object that implements the same interface.
If you understand what inheritance is, then another way to think about interfaces is that they are the same as the class, but they have no implementation. Therefore, when a class inherits from another class, it inherits both the inteface and implementation classes. If a class inherits only an interface, then it lacks an implementation, and the new class itself must create this implementation.
The delegate is completely different. A delegate is, among other things, a pointer to a function that is an object. A function pointer is a variable similar to other variables, but it is “delegate” and not “int” or “string”. And instead of storing data, it contains a pointer to a method (along with some status information) so that you can dynamically call different functions at run time.
In the following code, the call to "foo" is fixed. At runtime, you cannot decide whether you want to call the "bar":
DoSometing() { foo(); }
If instead you did something like the following, you can pass different methods as arguments to your method and call them dynamically:
DoSomething(MyFunction func) { MyFunction myfunc = func; myfunc(); }
Delegates can do more than that, but this is the main way to think about them.