Делегат это не указатель на функцию, а это объект динамически размещаемый в куче и лишний раз почём зря напрягающий своей тушкой сборщик мусора. Внутри тушки делегатного объекта лежит указатель на таргетный объект "делегировавший" его и особым образом закодирована информация о методе таргетного объекта, который через этот делегат можно вызвать. Особым образом закодирована означает, что там не обязательно адрес начала кода процедуры ибо ежели процедуру ни разу не вызвали, то и машинный код для неё не генерировался (в дотнете JIT компиляция). И лишь только благодаря синтаксическому сахару языка C# делегат в исходном тексте программы может выглядеть (а может и не выглядеть) как "указатель на функцию". Однако это не мешает работать с ним (в случае необходимости) как с обыкновенным дотнетным объектом. Как у обычного объекта у него есть методы:
* получения таргетного объекта,
* получения объекта метаинформации о процедуре,
* и конечно все стандартные методы отнаследованные от базового System.Object.
Естественно он является GC-якорем для таргетного объекта. Ну ещё с помощью них можно мультикаст делать (ещё одна сладкая плюшка для ленивых) и вызывать в отдельном потоке взятом из пула потоков.

Делегаты применяются теми кому лень писать "много" исходного текста, а оверхед по памяти/скорости их не волнует, то есть когда приоритет отдаётся скорости написания исходного текста программы в ущерб её производительности.