tl;dr(まとめ)
C#のデリゲートは、 引数として関数を1つ受けとるデータ型(参照型) の一種です。
C#には他にもnewキーワードで生成するデータ型としてクラス、構造体があります。
C#のデリゲートは、+, - 演算子を持ち、一つのデリゲート変数に複数のデリゲートを登録することが出来、 マルチキャスト と呼ばれる機能を持ちます。
(これが、C#のデリゲートの特筆すべき機能だと思います。)
書いたこと
- デリゲートの宣言
- デリゲートの生成と実行
 3. newキーワドによる生成
 4. 匿名メソッドによる生成
 5. ラムダ式による生成
- デリゲートの+-演算 (マルチキャスト)
デリゲートの宣言
デリゲートの宣言
delegate 戻り値の型 デリゲート名 (関数が引き受ける仮引数);
例: 「2つのint型の引数を受け取りint型の値を返す関数」のデリゲート宣言
Calculateデリゲートの宣言
// Calculateデリゲートの宣言
delegate int Calculate (int a, int b);
- 仮引数名が要ることが残念ですね。
デリゲートの生成と実行
newキーワードによる生成
newキーワードによるデリゲートの生成
using System;
// デリゲートの宣言
delegate void Printer (string s);
class Test {
    public static void Main() {
        // デリゲートの生成
        Printer print = new Printer(Console.WriteLine);
        // デリゲートの実行
        print("Hello World");
    }
}
- 引数としてクラスメソッド、もしくはインスタンスメソッドを受け取る
匿名メソッドによる生成
匿名メソッドによるデリゲートの生成
using System;
// デリゲートの宣言
delegate void Printer (string s);
class Test {
    public static void Main() {
        // デリゲートの生成
        Printer print = delegate (string s) {
            Console.WriteLine(s);
        };
        // デリゲートの実行
        print("Hello World");
        // 匿名メソッドはデリゲート変数に代入することも可能
        print = delegate (string s) {
            Console.WriteLine($"You inputed \"{s}\"");
        };
        print("I'm fine");
    }
}
/* 実行結果
Hello World
You inputed "I'm fine"
*/
- delegateキーワードを使うことで匿名メソッドを定義することが出来る
- 匿名メソッドはデリゲートの初期化もしくはデリゲート変数に代入する事ができる。
- つまり匿名メソッドはデリゲートを生成する
ラムダ式による生成
ラムダ式によるデリゲートの生成
using System;
// デリゲートの宣言
delegate void Printer (string s);
class Test {
    public static void Main() {
        Printer print = (string s) => {
            Console.WriteLine($"You inputed \"{s}\"");
        };
        print("I'm fine");
    }
}
- ラムダ式も匿名メソッドと同じ様に、デリゲート変数の初期化、もしくは代入を行うことが出来る。
- つまりラムダ式もデリゲートを生成する
デリゲートの+-演算 (マルチキャスト)
C#のデリゲートは一つのデリゲート変数に複数のデリゲートを登録することが出来ます。
( マルチキャスト機能 と呼ばれます。)
マルチキャストによる複数のデリゲートの登録
using System;
// デリゲートの宣言
delegate void Calculator (int other);
class Test {
    public static void Main() {
        var i = new Integer(5);
        // 一つのデリゲート変数に複数のデリゲートを登録できる
        var calculator = new Calculator(i.Add) + new Calculator(i.Sub) + new Calculator(i.Mul);
        // デリゲートを実行
        calculator(5);
        Console.WriteLine("-- 引き算を削除 --");
        // 登録したデリゲートを削除することが出来る 
        calculator -= new Calculator(i.Sub);
        // デリゲートを実行
        calculator(10);
    }
}
class Integer {
    public int val;
    public Integer(int n) {
        val = n;
    }
    public void Add(int n) {
        Console.WriteLine($"足し算の結果は: {val + n}です。");
    }
    public void Sub(int n) {
        Console.WriteLine($"引き算の結果は: {val - n}です。");
    }
    public void Mul(int n) {
        Console.WriteLine($"掛け算の結果は: {val * n}です。");
    }
}
/* 実行結果
足し算の結果は: 10です。
引き算の結果は: 0です。
掛け算の結果は: 25です。
-- 引き算を削除 --
足し算の結果は: 15です。
掛け算の結果は: 50です。
*/
- 
+演算子を使って追加登録
- 
-演算子を使って登録から削除
Appendix
匿名メソッド
匿名メソッドの定義
delegate (仮引数) {
    // 式
}
- 生成するデリゲートの型は、コンパイラが推論してくれる
ラムダ式
ラムダ式
(仮引数) => {
    // 式
}
- 生成するデリゲートの型は、コンパイラが推論してくれる