ラムダ式(Lambda expressions)を理解しよう!

[C#] ラムダ式(Lambda expressions)を理解しよう!

※ 当サイトは広告を含みます。

ここではC#のラムダ式を学習します。個人的にC#で1番好きな記述方法です。

いわゆる簡易記述になり、ラムダ式を使わない記述もできます。
ただ、実際は必須です。これを覚えないと現実的なコードが書けません。

ラムダ式(Lambda expressions)

ラムダ式とは、メソッド(関数)を定義せずに直接記述する方法です。

りさ
りさ

言ってる意味が分かりません。

管理人
管理人

正直、いい感じの説明がない。上の説明も合ってるか怪しい。

と言うことで、実際のラムダ式を体験しましょう。
たぶん、見たほうが早いです。てか、見て覚えて。

最初にラムダ式に変換する前のサンプルコードです。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      var _action = new Action(Method);
      _action();
    }

    private static void Method()
    {
      Console.WriteLine($"Method()が実行された");
    }
  }
}

これはデリゲートを活用して間接的にメソッドを呼ぶパターンです。

Action型.NETに標準定義されてるクラスで、引数も戻り値も持たないメソッドを意味します。
他にも同系統が色々と定義されていて、基本的にジェネリック型で存在します。

大雑把に言うと、Action型Func型があって戻り値の有無で利用する種類が決まります。
前者のAction型は戻り値がない場合、後者のFunc型は戻り値がある場合に使います。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      // Action型
      var _action = new Action<string, int>(ActionMethod);
      _action("りさ", 15);

      // Func型
      var _func = new Func<int, int, int>(FuncMethod);
      var r = _func(2, 10);
      Console.WriteLine($"r={r}");
    }

    // Action型で使うメソッド
    private static void ActionMethod(string s, int i)
    {
      Console.WriteLine($"Method(s={s}, i={i})が実行された");
    }

    // Func型で使うメソッド
    private static int FuncMethod(int a, int b)
    {
      return a * b;
    }
  }
}

こんな感じに引数の数だけ任意の型を指定します。なお、Func型は戻り値があるので1つ多くなります。
ちなみに引数が15個くらいなら.NETに標準定義されてます。なので、通常利用なら自作は不要です。

では、これを本題のラムダ式に変換してみましょう。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      // ラムダ式
      var _action = (
        () =>
        {
          Console.WriteLine($"Method()が実行された");
        }
      );

      _action();
    }
  }
}

これは引数も戻り値もないパターンですね。1番シンプルな形だと思います。
全体の()は省略して記述することもできますが、今回は見た目の分かりやすさを重視しました。

次に引数と戻り値があるパターンです。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      // ラムダ式
      var _func = (
        (int a, int b) =>
        {
          return a * b;
        }
      );

      var r = _func(2, 10);

      Console.WriteLine($"r={r}");
    }
  }
}

こんな感じにメソッドを式として直接記述できるのがラムダ式です。
この手法を覚えると、参照する外部メソッドを作成する必要がなくなります。

管理人
管理人

これによりコードは分離せず、命名に割く無駄な時間も減ります。

省略形

ラムダ式は処理部分、つまり{}の中身がプログラム的に1行なら{}returnを省略して記述できます。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      // ラムダ式(省略)
      var _func = (int a, int b) => a * b;

      var r = _func(2, 10);

      Console.WriteLine($"r={r}");
    }
  }
}

さらに引数も型推論が機能するので、型が明確な場合は型指定は不要です。
これはイベントの学習で利用したサンプルコードです。ラムダ式を使わないパターンになります。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      // 指定したディレクトリを監視するクラス
      using var watcher = new System.IO.FileSystemWatcher(@"C:\Temp");

      // ディレクトリまたはファイルが作成された場合のイベント
      watcher.Created += Watcher_OnCreated;

      // ディレクトリまたはファイルが削除された場合のイベント
      watcher.Deleted += Watcher_OnDeleted;

      // イベントの有効化
      watcher.EnableRaisingEvents = true; // ※ FileSystemWatcherを使う場合は必要

      // Enterが入力されるまでプログラムを続行
      Console.WriteLine("Enterを入力すると終了します。");
      Console.ReadLine();
    }

    // ディレクトリまたはファイルが作成された場合に呼び出されるメソッド
    private static void Watcher_OnCreated(object sender, FileSystemEventArgs e)
    {
      Console.WriteLine($"ファイルが作成されました。FullPath={e?.FullPath}");
    }

    // ディレクトリまたはファイルが削除された場合に呼び出されるメソッド
    private static void Watcher_OnDeleted(object sender, FileSystemEventArgs e)
    {
      Console.WriteLine($"ファイルが削除されました。FullPath={e?.FullPath}");
    }
  }
}

これをラムダ式を利用して書き換えます。
型推論により引数の型は不要になります。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      // 指定したディレクトリを監視するクラス
      using var watcher = new System.IO.FileSystemWatcher(@"C:\Temp");

      // (ラムダ式) ディレクトリまたはファイルが作成された場合のイベント
      watcher.Created += (s, e) => Console.WriteLine($"ファイルが作成されました。FullPath={e?.FullPath}");

      // (ラムダ式) ディレクトリまたはファイルが削除された場合のイベント
      watcher.Deleted += (s, e) => Console.WriteLine($"ファイルが削除されました。FullPath={e?.FullPath}");

      // イベントの有効化
      watcher.EnableRaisingEvents = true; // ※ FileSystemWatcherを使う場合は必要

      // Enterが入力されるまでプログラムを続行
      Console.WriteLine("Enterを入力すると終了します。");
      Console.ReadLine();
    }
  }
}

注意点として、ラムダ式で記述したメソッドは名前を持ちません。故に登録したイベントハンドラを削除することもできません。
と言うか、基本的に名称を指定するような処理はラムダ式では利用不可能です。必要なら素直にメソッド化してください。

Tipsラムダ式はプロパティなどにも利用できます。あくまで簡易記述する手法をラムダ式と呼びます。

あとがき

メソッドの命名って凄く手間なので、ラムダ式を利用することで、それを回避できるのが便利です。
後はLINQと呼ばれる便利機能がC#に存在するのですが、ラムダ式なしではLINQを記述するのがほぼほぼ不可能です。

◆ C#に関する学習コンテンツ

この記事は参考になりましたか?

関連記事

コメント

この記事へのコメントはありません。