CS801~2000

C#コンパイラーエラーCS1938について解説:join句で発生するequalsエラーの原因と対処法

C#のコンパイラーエラーCS1938は、join句でequals演算子を使用する際に左右の変数スコープの不一致が原因で発生します。

具体的には、右側に記述した変数が認識されずエラーとなるため、変数の順序を入れ替えて記述する必要があります。

エラーCS1938の原因解説

C#のjoin句では、equals演算子を用いて2つのシーケンスの要素を紐付ける際に、キーとなる値の比較を行います。

equals演算子は、左右に指定された式の値が等しいかどうかを判断するために使われます。

ここで注意すべきは、join句における左右の変数(範囲変数)は異なるスコープに属している点です。

これにより、不適切な変数の記述順序が原因でエラーCS1938が発生する場合があります。

join句におけるequals演算子の役割

join句のequals演算子は、左側のシーケンスの各要素と右側のシーケンスの各要素との間で、キーとなる値が一致するかを確認します。

具体的には、例えばソース配列sourceAsourceBがある場合、equals演算子によって2つの配列内の値が等しいかチェックされ、一致する場合に新しい匿名型が生成されます。

このとき、左側の変数はjoin句の全体で有効であり、右側の変数は左側の変数のスコープ内でしか使用できないため、変数の位置が重要になります。

範囲変数のスコープ制約

join句を使用する際の範囲変数は、定義された位置によって有効範囲が決まっています。

左側のシーケンスから得られる変数はjoin句全体で利用可能ですが、右側のシーケンスからの変数は左側側のスコープ内に限定されます。

これにより、equals演算子の左右で同名の変数や、意図しない変数の参照が起こるとコンパイルエラーとなる可能性があります。

左側と右側の変数の定義と適用範囲

  • 左側の変数は、from句とjoin句の序盤で定義され、equals演算子の左側とその後のselect句、あるいはinto句で継続して利用できます。
  • 右側の変数は、join句内でのみ定義され、equals演算子の右側で使用されます。

たとえば、以下のコード例では、sourceAの変数ajoin句全体で有効ですが、sourceBの変数bequals部分での参照に限定されるため、位置が逆転するとエラーが発生します。

コード例によるエラー検証

エラーの発生原因を明確に把握するため、サンプルコードを用いてエラーの発生状況を確認します。

エラー発生コードの紹介

以下のコードは、join句において左右の変数の順序が誤っているためにコンパイルエラー CS1938 が発生する例です。

コード内のコメントにてエラーの原因を示しています。

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        // サンプル配列を初期化
        int[] sourceA = { 1, 2, 3, 4, 5 };
        int[] sourceB = { 3, 4, 5, 6, 7 };
        // join句においてequalsの左右を逆にしているためエラーが発生する
        var query = from a in sourceA
                    join b in sourceB on b equals a   // CS1938が発生する箇所
                    select new { a, b };
        // 結果の出力(実際にはこの部分に到達しません)
        foreach (var item in query)
        {
            Console.WriteLine($"a: {item.a}, b: {item.b}");
        }
    }
}
// コンパイル時に以下のようなエラーメッセージが出力されます。
// 名前 'name' は、'equals' の右側のスコープにありません。
// 'equals' のいずれかの側で式の交換を検討してください。

コンパイル時のエラーメッセージ詳細

上記のコードをコンパイルすると、エラーメッセージにて「名前 ‘name’ は、’equals’ の右側のスコープにありません」と表示されます。

このエラーは、join句内でequals演算子の左右が逆になっているため、右側の変数が左側のスコープに存在しないことが原因です。

C#コンパイラーは、左右の変数の有効範囲が異なるため、equals演算子の左右を正しい順序で記述するよう求めています。

エラー修正方法の解説

エラーCS1938を解消するためには、join句における左右の変数の位置を正しく入れ替える必要があります。

以下では、正しい書き方とその手順について解説します。

変数の順序変更による修正手順

エラーを修正するためには、join句内でequals演算子の左右に記述する変数を入れ替えます。

具体的には、以下の変更を行います。

  • 修正前:join b in sourceB on b equals a
  • 修正後:join b in sourceB on a equals b

この変更により、左側にあるaと右側にあるbが正しく対応し、スコープの制約が解消されます。

修正前後のコード比較

下記の比較表をご確認ください。

・修正前

  • join句: join b in sourceB on b equals a

・修正後

  • join句: join b in sourceB on a equals b

以下に、修正後のコード全体を示します。

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        // サンプル配列の初期化
        int[] sourceA = { 1, 2, 3, 4, 5 };
        int[] sourceB = { 3, 4, 5, 6, 7 };
        // join句内で変数aとbの位置を正しく指定
        var query = from a in sourceA
                    join b in sourceB on a equals b   // 修正済み
                    select new { a, b };
        // クエリ結果の出力
        foreach (var item in query)
        {
            Console.WriteLine($"a: {item.a}, b: {item.b}");
        }
    }
}
a: 3, b: 3
a: 4, b: 4
a: 5, b: 5

修正後の検証方法

修正後は、以下の手順で動作確認を行ってください。

  1. コードを保存し、プロジェクトを再コンパイルしてください。
  2. コンパイルエラーが解消されることを確認してください。
  3. プログラムを実行し、出力が期待通り(例では一致する値のみが表示される)になっているか確認してください。

これらの検証により、修正が正しく反映され、エラーCS1938が解消されたことが確認できます。

エラー修正時の注意点

エラーを修正する際には、コードの他の部分への影響についても確認が必要です。

特に、複数のjoin句を使用している場合、変数の順序変更が他の処理に影響を与えないかを慎重に検証してください。

また、修正後に結合条件が正しく反映され、データの整合性が保たれているかを確認することが大切です。

コード変更時の影響確認と留意点

  • 変更した箇所が他のクエリロジックや処理に影響を与えていないか確認してください。
  • 複雑なクエリの場合、結合条件の変更により意図しない結合結果が出力されないよう、テストケースを十分に用意してください。
  • チームで開発している場合、変更箇所を共有し、他の開発者との間で認識のズレがないか確認することが重要です。

まとめ

この記事では、C#のjoin句で発生するエラーCS1938の原因と対策について解説しています。

equals演算子の左右に割り当てられる範囲変数のスコープ制約を理解することが、エラー解消の鍵であることがわかります。

具体的なコード例を用い、変数の順序変更による修正手順や、修正後の検証方法、さらにはコード変更時の影響確認について説明しています。

関連記事

Back to top button
目次へ