0Pricing
C# Academy · レッスン

静的ローカル関数

明確さとパフォーマンスのためにキャプチャを防ぎます。

「静的ローカル関数」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

static ローカル関数

ローカル関数に static を付けると、外側の変数や this をキャプチャできなくなります。これにより、関数が自己完結し、意図が明確になり、隠れたクロージャの割り当ても発生しません。

static ローカル関数を宣言する

戻り値の型の前に static 修飾子を追加します。関数は引き続きパラメーターを受け取り、値を返せますが、外側のローカル変数にはアクセスできません。

using System;

public class Program
{
    public static void Main()
    {
        static int Square(int n) => n * n; // captures nothing

        Console.WriteLine(Square(6));
    }
}

キャプチャは禁止される

static ローカル関数は、外側のローカル変数を使用できません。必要なものはすべてパラメーターとして渡す必要があるため、入力が明示的になります。

using System;

public class Program
{
    public static void Main()
    {
        int factor = 3;
        // factor must be passed in, not captured
        static int Scale(int n, int f) => n * f;

        Console.WriteLine(Scale(5, factor));
    }
}

隠れた割り当てを避ける

変数をキャプチャする非 static ローカル関数では、隠れたクロージャオブジェクトが割り当てられることがあります。static ローカル関数は決してキャプチャしないため、その割り当てを完全に回避できます。

using System;

public class Program
{
    public static void Main()
    {
        // Pure helper, no closure object created
        static bool IsEven(int n) => n % 2 == 0;

        for (int i = 0; i < 5; i++)
            Console.WriteLine(i + ": " + IsEven(i));
    }
}

意図を自己文書化する

static キーワードは、そのヘルパーが引数だけに依存することを読み手に示します。この保証により、関数の動作を推測しやすくなり、テストもしやすくなります。

using System;

public class Program
{
    public static void Main()
    {
        static int Clamp(int value, int lo, int hi)
            => value < lo ? lo : value > hi ? hi : value;

        Console.WriteLine(Clamp(15, 0, 10));
        Console.WriteLine(Clamp(-3, 0, 10));
    }
}

コンパイラーがキャプチャなしを強制する

static ローカル関数内で外側のローカル変数を誤って参照すると、コンパイラーがエラーを報告します。これにより、意図しない依存関係を早期に検出できます。

using System;

public class Program
{
    public static void Main()
    {
        int seed = 7;
        // Correct: seed is passed explicitly, not captured
        static int Mix(int x, int s) => x * 31 + s;

        Console.WriteLine(Mix(2, seed));
    }
}

static ローカル関数での再帰

static ローカル関数でも再帰を利用できます。自分自身を呼び出すことは、変数をキャプチャすることとは異なるためです。

using System;

public class Program
{
    public static void Main()
    {
        static int Power(int baseN, int exp)
            => exp == 0 ? 1 : baseN * Power(baseN, exp - 1);

        Console.WriteLine(Power(2, 10));
    }
}

out パラメーターと組み合わせる

通常のメソッドと同様に、static ローカル関数では out パラメーターを使用できます。キャプチャを行わない性質と相性がよく、TryParse 形式のヘルパーに適しています。

using System;

public class Program
{
    public static void Main()
    {
        static bool TryParsePositive(string s, out int value)
        {
            value = 0;
            return int.TryParse(s, out value) && value > 0;
        }

        if (TryParsePositive("42", out int n))
            Console.WriteLine("got " + n);
        Console.WriteLine(TryParsePositive("-1", out _));
    }
}

static ローカル関数をデリゲートとして渡す

static ローカル関数は何もキャプチャしないため、クロージャを割り当てずにデリゲートへ変換できます。これは、頻繁に実行される処理で重要になる場合があります。

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        static bool IsBig(int n) => n > 100;

        var nums = new List<int> { 50, 150, 200, 10 };
        Console.WriteLine(nums.Count(IsBig));
    }
}

static を優先する場面

ヘルパーが外側の状態を必要としない場合は、static ローカル関数を優先します。純粋な関数であることを示し、意図しないキャプチャを防ぎ、より効率的になる可能性があります。ローカル変数をキャプチャする必要が本当にある場合にだけ static を外します。

using System;

public class Program
{
    public static void Main()
    {
        static string Describe(int score)
        {
            if (score >= 90) return "A";
            if (score >= 80) return "B";
            return "C";
        }

        Console.WriteLine(Describe(95));
        Console.WriteLine(Describe(82));
    }
}

自分で試す

純粋な static ローカル関数を記述し、LINQ の述語として渡します。何もキャプチャしないため、クロージャなしでデリゲートに変換できます。

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        static bool IsLeapYear(int year)
            => (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;

        var years = new List<int> { 1900, 2000, 2004, 2021, 2024 };
        Console.WriteLine(string.Join(", ", years.Where(IsLeapYear)));
    }
}

クイックチェック

static をローカル関数に追加すると何が起こるかを思い出してください。

まとめ

static ローカル関数は何もキャプチャしません。

  • 外側のローカル変数や this を使用できないため、データはパラメーターで渡します。
  • 隠れたクロージャの割り当てを回避できます。
  • コンパイラーがキャプチャなしのルールを強制し、意図しない依存関係を検出します。
  • ヘルパーが外側の状態を必要としない場合は、これを優先します。

よくある質問

「静的ローカル関数」レッスンは無料ですか?

はい。「静的ローカル関数」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「静的ローカル関数」で何を学びますか?

明確さとパフォーマンスのためにキャプチャを防ぎます。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「静的ローカル関数」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ローカル関数の宣言
  2. クロージャーとキャプチャされた変数
  3. 静的ローカル関数
  4. ローカル関数とラムダの比較
← C# Academyに戻る