コンパイラ エラー CS8352

参照される変数が宣言のスコープ外に公開される可能性があるため、このコンテキストで変数 'variable' を使用することはできません。

このエラーは、スタックから既に削除された後に、スタックに割り当てられた変数にアクセスするリスクがある場合に、未定義の動作が発生する可能性があることを示します。

このエラーを解決するには

変数のスコープが、少なくともそれを参照する変数と同じ幅であることを確認して、CS8352 を修正します。 ヒープにストレージを割り当てるか、コンテキストの呼び出しのスタックに割り当てることで、これを行います。

次の例では CS8352 が生成されます。

class Program
{
    static public Span<int> CreateSpanWithValue(int size, int value)
    {
        Span<int> localSpan = stackalloc int[size];
        localSpan[0] = value;
        return localSpan;    // CS8352
    }                        // localSpan refers to stack memory that's been reclaimed.

    static public void Main()
    {
        Span<int> localSpan = CreateSpanWithValue(5, 10);
        localSpan[2] = 14;
        foreach(var item in localSpan)
        {
            Console.WriteLine(item.ToString());  // Reading from deleted object
        }
    }
    // Example of output:
    // 284945320
    // 149
    // 149
    // 1369466325
    // 284945320
}

次の例では、スタック割り当てを移動して、そのスコープ Span と一致するようにしています。
スパンが参照するメモリはスタックに割り当てられるものの、コンテキストの呼び出しに割り当てられるため、このソリューションの例は機能します。

class Program
{
    static public void FillSpanWithValue(Span<int> span, int value)
    {
        span[0] = value;
    }

    static public void Main()
    {
        Span<int> localSpan = stackalloc int[5];
        FillSpanWithValue(localSpan, 10);
        localSpan[2] = 14;
        foreach(var item in localSpan)
        {
            Console.WriteLine(item.ToString());
        }
    }
    // Output:
    // 10
    // 0
    // 14
    // 0
    // 0
}

次のサンプルでは、new キーワードを使用して、スタックではなくヒープ上にオブジェクトを作成しています。
CreateSpanWithValue メソッドから戻った後、スパンが参照するメモリはスタック上ではなくヒープ上に割り当てられるため、引き続き有効であるため、このソリューションの例は機能します。

class Program
{
    static public Span<int> CreateSpanWithValue(int size, int value)
    {
        Span<int> localSpan = new int[size];
        localSpan[1] = value;
        return localSpan;
    }

    static public void Main()
    {
        var span = CreateSpanWithValue(5, 10);
        span[2] = 14;
        foreach(var item in span)
        {
            Console.WriteLine(item.ToString());
        }
    }
    // Output:
    //0
    //10
    //14
    //0
    //0
}

関連項目