次の方法で共有


Global Using ディレクティブ

この記事は機能仕様です。 仕様は、機能の設計ドキュメントとして機能します。 これには、提案された仕様の変更と、機能の設計と開発時に必要な情報が含まれます。 これらの記事は、提案された仕様の変更が最終決定され、現在の ECMA 仕様に組み込まれるまで公開されます。

機能の仕様と完成した実装の間には、いくつかの違いがある可能性があります。 これらの違いは、関連する 言語設計会議 (LDM) ノートでキャプチャされます。

機能仕様を C# 言語標準に導入するプロセスの詳細については、仕様に関する記事を参照してください。

チャンピオン号: https://github.com/dotnet/csharplang/issues/3428

using ディレクティブの構文は、global キーワードの前に置くことができる省略可能な using キーワードで拡張されます。

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

global_using_directive
    : global_using_alias_directive
    | global_using_namespace_directive
    | global_using_static_directive
    ;

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;
    
global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;
  • global_using_directiveはコンパイル ユニット レベルでのみ許可されます (namespace_declaration内では使用できません)。
  • global_using_directiveがある場合は、using_directiveの前に置く必要があります。
  • global_using_directiveのスコープは、プログラム内のすべてのコンパイル 単位のnamespace_member_declarationに拡張されます。 global_using_directiveのスコープには、特に他のglobal_using_directiveは含まれません。 したがって、ピア global_using_directiveまたは別のコンパイル単位のピアは互いに影響を与えるのではなく、記述される順序は重要ではありません。 global_using_directiveのスコープには、プログラムのコンパイル単位にすぐに含まれるusing_directiveは特に含まれません。

プログラムに global_using_directive を追加する効果は、同じターゲット名前空間または型に解決される同様の using_directive をプログラムのすべてのコンパイル単位に追加する効果と考えることができます。 ただし、 global_using_directive のターゲットは、それを含むコンパイルユニットのコンテキストで解決されます。

§7.7 スコープ

これらは、提案された追加の関連する箇条書きです (太字)。

  • extern_alias_directiveによって定義された名前のスコープは、すぐに含まれるコンパイルユニットまたは名前空間本体のglobal_using_directiveusing_directiveglobal_attributes、およびnamespace_member_declarationに拡張されます。 extern_alias_directiveは、基になる宣言空間に新しいメンバーを提供しません。 言い換えると、 extern_alias_directive は推移的ではなく、むしろ、それが発生するコンパイル単位または名前空間本体にのみ影響します。
  • global_using_directiveによって定義またはインポートされた名前のスコープは、プログラム内のすべてのcompilation_unitglobal_attributesnamespace_member_declarationに拡張されます。

§7.8 名前空間と型の名前

namespace_or_type_nameの意味を決定するアルゴリズムを次のように変更します。

これは、提案された追加を含む関連する箇条書きです (太字)。

  • namespace_or_type_nameがフォーム Iまたはフォーム I<A1, ..., Ak>の場合:
    • Kが 0 で、namespace_or_type_nameがジェネリック メソッド宣言 (§15.6) 内に表示され、その宣言に名前を持つ型パラメーター (I) が含まれている場合、namespace_or_type_nameはその型パラメーターを参照します。
    • それ以外の場合、 namespace_or_type_name が型宣言内に出現する場合は、各インスタンス型 T (§15.3.2) に対して、その型宣言のインスタンス型から始まり、外側にある各クラスまたは構造体宣言のインスタンス型 (存在する場合) を続行します。
      • Kが 0 で、Tの宣言に名前Iを持つ型パラメーターが含まれている場合、namespace_or_type_nameはその型パラメーターを参照します。
      • それ以外の場合、 namespace_or_type_name が型宣言の本体内に表示され、 T またはその基本型に名前 I および K 型パラメーターを持つ入れ子になったアクセス可能な型が含まれている場合、 namespace_or_type_name は、指定された型引数で構築されたその型を参照します。 このような型が複数存在する場合は、より多くの派生型内で宣言された型が選択されます。 型パラメーターの数が異なる型メンバー (定数、フィールド、メソッド、プロパティ、インデクサー、演算子、インスタンス コンストラクター、デストラクター、および静的コンストラクター) および型メンバーは、 namespace_or_type_nameの意味を決定するときに無視されることに注意してください。
    • 前の手順が失敗した場合は、各名前空間 Nについて、 namespace_or_type_name が発生する名前空間から始まり、外側の名前空間 (存在する場合) ごとに続行され、グローバル名前空間で終わる場合は、エンティティが配置されるまで次の手順が評価されます。
      • K が 0 で、 IN内の名前空間の名前である場合は、次のようになります。
        • namespace_or_type_nameが発生する場所がNの名前空間宣言で囲まれており、名前空間宣言に名前空間または型に名前を関連付けるextern_alias_directiveまたはIが含まれている場合は、プログラム内のNの名前空間宣言に名前空間または型に名前を関連付けるIが含まれています。namespace_or_type_nameはあいまいであり、コンパイル時エラーが発生します。
        • それ以外の場合、namespace_or_type_nameIN という名前の名前空間を参照します。
      • それ以外の場合、 N に名前 I および K 型パラメーターを持つアクセス可能な型が含まれている場合は、次のようになります。
        • Kが 0 で、namespace_or_type_nameが発生する場所がNの名前空間宣言で囲まれており、名前空間宣言に名前空間または型に名前を関連付けるextern_alias_directiveまたはIが含まれている場合は、プログラム内のNのすべての名前空間宣言に、名前を名前空間または型に関連付けるIが含まれます。namespace_or_type_nameはあいまいであり、コンパイル時エラーが発生します。
        • それ以外の場合、 namespace_or_type_name は、指定された型引数で構築された型を参照します。
      • それ以外の場合、 namespace_or_type_name が発生する場所が Nの名前空間宣言で囲まれている場合:
        • Kが 0 で、名前をインポートされた名前空間または型に関連付けるextern_alias_directiveまたはIが名前空間宣言に含まれている場合、またはプログラム内のNの名前空間宣言には、インポートされた名前空間または型に名前を関連付けるIが含まれますnamespace_or_type_nameはその名前空間または型を参照します。
        • それ以外の場合、名前空間宣言のusing_namespace_directiveusing_alias_directiveによってインポートされた名前空間と型宣言、およびプログラム内のの名前空間宣言のglobal_using_namespace_directiveNによってインポートされた名前空間と型宣言名前IK型パラメーターを持つアクセス可能な型が 1 つだけ含まれます。 その後、namespace_or_type_nameは、指定された型引数で構築された型を参照します。
        • それ以外の場合は、名前空間宣言のusing_namespace_directiveusing_alias_directiveによってインポートされた名前空間と型宣言、プログラム内のの名前空間宣言のglobal_using_namespace_directiveNによってインポートされた名前空間と型宣言名前IK型パラメーターを持つ複数のアクセス可能な型が含まれます。 その場合、namespace_or_type_nameはあいまいであり、エラーが発生します。
    • それ以外の場合、 namespace_or_type_name は未定義であり、コンパイル時エラーが発生します。

単純な名前 §12.8.4

simple_name評価規則に対して次のように変更が加えられます。

これは、提案された追加を含む関連する箇条書きです (太字)。

  • それ以外の場合は、Nごとの名前空間に対して、simple_name が存在する名前空間から始まり、外側の各名前空間 (存在する場合) を続行し、グローバル名前空間で終わるまで、エンティティが見つかるまで、次のステップが評価されます。
    • K が 0 で、 IN内の名前空間の名前である場合は、次のようになります。
      • simple_nameが発生する場所がNの名前空間宣言で囲まれており、名前空間宣言に名前空間または型に名前を関連付けるextern_alias_directiveまたはIが含まれている場合は、またはプログラム内のNの名前空間宣言に、名前空間または型に名前を関連付けるIが含まれています。simple_nameはあいまいであり、コンパイル時エラーが発生します。
      • それ以外の場合、 simple_nameIN という名前の名前空間を参照します。
    • それ以外の場合、 N に名前 I および K 型パラメーターを持つアクセス可能な型が含まれている場合は、次のようになります。
      • Kがゼロで、simple_nameが発生する場所がNの名前空間宣言で囲まれており、名前空間宣言に名前空間または型に名前を関連付けるextern_alias_directiveまたはIが含まれている場合、プログラム内のNの名前空間宣言に名前空間を名前空間または型に関連付けるIが含まれます。simple_nameがあいまいになり、コンパイル時エラーが発生します。
      • それ以外の場合、 namespace_or_type_name は、指定された型引数で構築された型を参照します。
    • それ以外の場合、simple_name が発生する場所が N の名前空間宣言で囲まれている場合:
      • Kがゼロで、名前をインポートされた名前空間または型に関連付けるextern_alias_directiveまたはIが名前空間宣言に含まれている場合、またはプログラム内のNの名前空間宣言には、インポートされた名前空間または型に名前を関連付けるIが含まれますsimple_nameはその名前空間または型を参照します。
      • それ以外の場合、名前空間宣言のusing_namespace_directiveusing_static_directiveによってインポートされた名前空間と型宣言、プログラム内のの名前空間宣言のglobal_using_namespace_directiveNによってインポートされた名前空間と型宣言名前IKを持つアクセス可能な型または非拡張静的メンバーが 1 つだけ含まれます。型パラメーターを指定すると、simple_nameは、指定された型引数で構築された型またはメンバーを参照します。
      • それ以外の場合は、名前空間宣言のusing_namespace_directiveによってインポートされた名前空間と型、プログラム内のの名前空間宣言のglobal_using_namespace_directiveNによってインポートされた名前空間と型宣言名前IK型パラメーターを持つ複数のアクセス可能な型または非拡張メソッドの静的メンバーが含まれます。 その場合、simple_nameがあいまいになり、エラーが発生します。

拡張メソッドの呼び出し §12.8.10.3

アルゴリズムに変更を加えて、次のように最適な type_nameC を見つけます。 これは、提案された追加を含む関連する箇条書きです (太字)。

  • 最も近い囲われた名前空間宣言から開始し、各囲われた名前空間宣言へ進み、含まれているコンパイル単位で終わります。拡張メソッドの候補セットを検索するために連続的に試行されます。
    • 指定された名前空間またはコンパイル単位に、適格な拡張メソッド Ci を持つ非ジェネリック型宣言 Mj が直接含まれている場合、それらの拡張メソッドのセットが候補セットになります。
    • Ciusing_static_declarationsによってインポートされ、指定された名前空間またはコンパイル 単位のusing_namespace_directiveによってインポートされた名前空間で直接宣言場合、コンパイル 単位に到達し、global_using_static_declarationsによってインポートされ、プログラム内のglobal_using_namespace_directiveによってインポートされた名前空間で直接宣言された場合Mjを選択すると、それらの拡張メソッドのセットが候補セットになります。

コンパイル単位 §14.2

compilation_unit は、ソース ファイルの全体的な構造を定義します。 コンパイル単位は、 ゼロ以上の global_using_directiveの後 0 個以上の using_directiveの後に 0 個以上の global_attributes が続き、その後に 0 個以上の namespace_member_declarationで構成されます。

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

C# プログラムは 1 つ以上のコンパイル 単位で構成され、それぞれが個別のソース ファイルに含まれています。 C# プログラムをコンパイルすると、すべてのコンパイル単位が一緒に処理されます。 したがって、コンパイル単位は、おそらく循環的に、互いに依存することができます。

コンパイル単位の global_using_directiveは、プログラム内のすべてのコンパイル ユニットの global_attributesnamespace_member_declarationに影響します。

Extern エイリアス §14.4

extern_alias_directiveのスコープは、すぐに含まれるコンパイルユニットまたは名前空間本体のglobal_using_directiveusing_directiveglobal_attributes、およびnamespace_member_declarationに拡張されます。

エイリアス ディレクティブの使用 §14.5.2

using_alias_directiveが書き込まれる順序には意味がなく、using_alias_directiveによって参照されるnamespace_or_type_nameの解決は、using_alias_directive自体、またはすぐに含まれるコンパイルユニットまたは名前空間本体の他のusing_directiveの影響を受けず、using_alias_directiveがコンパイルユニットにすぐに含まれている場合、 は、プログラム内のglobal_using_directiveの影響を受けません。 つまり、using_alias_directivenamespace_or_type_nameは、すぐに含まれるコンパイルユニットまたは名前空間本体にusing_directiveがないかのように解決されます。また、using_alias_directiveがコンパイルユニットにすぐに含まれている場合、プログラムにはglobal_using_directive。 ただし、 using_alias_directive は、すぐに含まれるコンパイルユニットまたは名前空間本体の extern_alias_directiveによって影響を受ける可能性があります。

エイリアス ディレクティブを使用するグローバル

global_using_alias_directiveは、プログラム内の名前空間または型のエイリアスとして機能する識別子を導入します。

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

global_using_alias_directiveを含むプログラムのコンパイル単位のメンバー宣言内では、global_using_alias_directiveによって導入された識別子を使用して、指定された名前空間または型を参照できます。

global_using_alias_directiveidentifierは、global_using_alias_directiveを含むプログラムのコンパイル単位の宣言領域内で一意である必要があります。

通常のメンバーと同様に、 global_using_alias_directiveによって導入された名前は、入れ子になったスコープ内の同様の名前のメンバーによって非表示になります。

global_using_alias_directiveの記述順序には意味がなく、global_using_alias_directiveによって参照されるnamespace_or_type_nameの解決は、global_using_alias_directive自体やプログラム内の他のglobal_using_directiveusing_directiveの影響を受けません。 つまり、global_using_alias_directivenamespace_or_type_nameは、すぐに含まれるコンパイル単位にusing_directiveがなく、含まれるプログラム全体にglobal_using_directiveがないかのように解決されます。 ただし、 global_using_alias_directive は、すぐに含まれるコンパイル ユニット内の extern_alias_directiveの影響を受ける可能性があります。

global_using_alias_directiveは、任意の名前空間または型のエイリアスを作成できます。

エイリアスを使用して名前空間または型にアクセスすると、宣言された名前を使用してその名前空間または型にアクセスするのとまったく同じ結果が得られます。

using エイリアスは、閉じた構築された型に名前を付けることができますが、型引数を指定しないと、バインドされていないジェネリック型宣言に名前を付けることはできません。

名前空間ディレクティブを使用するグローバル

global_using_namespace_directiveは、名前空間に含まれる型をプログラムにインポートし、修飾なしで各型の識別子を使用できるようにします。

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;

global_using_namespace_directiveを含むプログラムのメンバー宣言内では、指定された名前空間に含まれる型を直接参照できます。

global_using_namespace_directiveは、特定の名前空間に含まれる型をインポートしますが、具体的には入れ子になった名前空間はインポートしません。

global_using_alias_directiveとは異なり、global_using_namespace_directiveは、プログラムのコンパイル単位内で識別子が既に定義されている型をインポートできます。 実際には、特定のコンパイル ユニットでは、プログラム内の任意の global_using_namespace_directive によってインポートされた名前は、コンパイル ユニット内の同様の名前付きメンバーによって非表示になります。

同じプログラム内の global_using_namespace_directiveまたは global_using_static_directiveによってインポートされた複数の名前空間または型に同じ名前の型が含まれている場合、 type_name としてのその名前への参照はあいまいと見なされます。

さらに、同じプログラム内の global_using_namespace_directiveまたは global_using_static_directiveによってインポートされた複数の名前空間または型に同じ名前の型またはメンバーが含まれている場合、その名前への参照が simple_name としてあいまいであると見なされます。

global_using_namespace_directiveによって参照されるnamespace_nameは、global_using_alias_directiveによって参照されるnamespace_or_type_nameと同じ方法で解決されます。 したがって、同じプログラム内の global_using_namespace_directiveは互いに影響を与えるのではなく、任意の順序で記述できます。

静的ディレクティブを使用するグローバル

global_using_static_directiveは、型宣言に直接含まれる入れ子になった型と静的メンバーを包含プログラムにインポートし、各メンバーと型の識別子を修飾なしで使用できるようにします。

global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;

global_using_static_directiveを含むプログラムのメンバー宣言内では、指定された型の宣言に直接含まれる、アクセス可能な入れ子になった型と静的メンバー (拡張メソッドを除く) を直接参照できます。

global_using_static_directiveでは、拡張メソッドを静的メソッドとして直接インポートするのではなく、拡張メソッドの呼び出しに使用できるようにします。

global_using_static_directiveは、基底クラスで宣言されたメンバーと型ではなく、指定された型で直接宣言されたメンバーと型のみをインポートします。

複数の global_using_namespace_directiveglobal_using_static_directives の間のあいまいさは、 global_using_namespace_directive (上記) のセクションで説明します。

修飾されたエイリアス メンバー §14.8

qualified_alias_memberの意味を決定するアルゴリズムを次のように変更します。

これは、提案された追加を含む関連する箇条書きです (太字)。

  • それ以外の場合は、すぐにqualified_alias_memberを格納する名前空間宣言 (§14.3) から始まり、外側の各名前空間宣言 (存在する場合) を続行し、qualified_alias_memberを含むコンパイル単位で終わると、エンティティが見つかるまで次の手順が評価されます。

    • を型 (or) に関連付けるNが名前空間宣言またはコンパイル 単位に含まれている場合、コンパイル単位に達すると、プログラムにを型に関連付けるNが含まれますqualified_alias_memberは未定義になり、コンパイル時エラーが発生します。
    • それ以外の場合、名前空間宣言またはコンパイル 単位に、Nを名前空間 *に関連付けるextern_alias_directiveまたはusing_alias_directiveが含まれている場合、コンパイル 単位に達すると、プログラムには、Nを名前空間に関連付けるglobal_using_alias_directiveが含まれます
      • Nに関連付けられている名前空間に I という名前の名前空間が含まれており、Kが 0 の場合、qualified_alias_memberはその名前空間を参照します。
      • それ以外の場合、 N に関連付けられている名前空間に I という名前の非ジェネリック型が含まれており、 K が 0 の場合、 qualified_alias_member はその型を参照します。
      • それ以外の場合、Nに関連付けられている名前空間に、K型パラメーターを持つ I という名前の型が含まれている場合、qualified_alias_memberは、指定された型引数で構築されたその型を参照します。
      • それ以外の場合、 qualified_alias_member は未定義であり、コンパイル時エラーが発生します。