クラスClasses

クラスは、データ メンバー (定数とフィールド)、関数メンバー (メソッド、プロパティ、イベント、インデクサー、演算子、インスタンス コンス トラクター、デストラクター、静的コンス トラクター)、および入れ子にされた型を含む可能性のあるデータ構造です。A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, destructors and static constructors), and nested types. クラス型では、継承、派生クラスが基底クラスを拡張および限定するためのメカニズムをサポートします。Class types support inheritance, a mechanism whereby a derived class can extend and specialize a base class.

クラス宣言Class declarations

A class_declarationは、 type_declaration (入力宣言) 新しいクラスを宣言します。A class_declaration is a type_declaration (Type declarations) that declares a new class.

class_declaration
    : attributes? class_modifier* 'partial'? 'class' identifier type_parameter_list?
      class_base? type_parameter_constraints_clause* class_body ';'?
    ;

A class_declarationオプションのセットから成る属性(属性) オプションのセットと、その後class_modifiers (修飾子をクラス) と省略可能なその後partialの後に、キーワード修飾子class識別子続く、クラスの名前を示す、省略可能なtype_parameter_list (パラメーター入力) と省略可能なその後class_base仕様 (クラスの基本仕様) オプションのセットと、その後type_parameter_constraints_clauses (パラメーターの制約入力)、その後に、 class_body (クラス本体)、セミコロンで必要に応じてその後にします。A class_declaration consists of an optional set of attributes (Attributes), followed by an optional set of class_modifiers (Class modifiers), followed by an optional partial modifier, followed by the keyword class and an identifier that names the class, followed by an optional type_parameter_list (Type parameters), followed by an optional class_base specification (Class base specification) , followed by an optional set of type_parameter_constraints_clauses (Type parameter constraints), followed by a class_body (Class body), optionally followed by a semicolon.

クラス宣言を提供できませんtype_parameter_constraints_clauses も用意されていない限り、 type_parameter_listします。A class declaration cannot supply type_parameter_constraints_clauses unless it also supplies a type_parameter_list.

クラスの宣言を提供する、 type_parameter_listは、ジェネリック クラス宣言します。A class declaration that supplies a type_parameter_list is a generic class declaration. さらに、ジェネリック クラス宣言またはジェネリック構造体宣言内で入れ子になったクラス自体がジェネリック クラス宣言では、含んでいる型の型パラメーターを指定して構築された型を作成する必要がありますので。Additionally, any class nested inside a generic class declaration or a generic struct declaration is itself a generic class declaration, since type parameters for the containing type must be supplied to create a constructed type.

クラスの修飾子Class modifiers

A class_declarationクラス修飾子のシーケンスを必要に応じて含めることができます。A class_declaration may optionally include a sequence of class modifiers:

class_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'abstract'
    | 'sealed'
    | 'static'
    | class_modifier_unsafe
    ;

同じ修飾子をクラス宣言内で複数回のコンパイル時エラーになります。It is a compile-time error for the same modifier to appear multiple times in a class declaration.

new修飾子を入れ子になったクラスを使用します。The new modifier is permitted on nested classes. 」の説明に従って、クラスが、同じ名前で、継承されたメンバーを非表示にするを指定します、 new 修飾子します。It specifies that the class hides an inherited member by the same name, as described in The new modifier. コンパイル時エラーには、new修飾子を入れ子になったクラス宣言ではないクラス宣言に表示されます。It is a compile-time error for the new modifier to appear on a class declaration that is not a nested class declaration.

publicprotectedinternal、およびprivate修飾子は、クラスのアクセシビリティを制御します。The public, protected, internal, and private modifiers control the accessibility of the class. クラス宣言が発生したコンテキストに応じてこれらの修飾子の一部は使用できません (宣言されたアクセシビリティ)。Depending on the context in which the class declaration occurs, some of these modifiers may not be permitted (Declared accessibility).

abstractsealedstatic修飾子は次のセクションで説明します。The abstract, sealed and static modifiers are discussed in the following sections.

抽象クラスAbstract classes

abstract修飾子を使用して、クラスが完了したと基本クラスとしてのみ使用するものであることを指定します。The abstract modifier is used to indicate that a class is incomplete and that it is intended to be used only as a base class. 抽象クラスは、次の方法で非抽象クラスとは異なります。An abstract class differs from a non-abstract class in the following ways:

  • 抽象クラスは、直接インスタンス化できないし、コンパイル時エラーに使用する、new抽象クラスでの演算子。An abstract class cannot be instantiated directly, and it is a compile-time error to use the new operator on an abstract class. 変数と値がコンパイル時の型が抽象クラスを含めることは可能ですが、このような変数と値は必ずしもなりますnullまたは抽象型から派生した非抽象クラスのインスタンスへの参照が含まれています。While it is possible to have variables and values whose compile-time types are abstract, such variables and values will necessarily either be null or contain references to instances of non-abstract classes derived from the abstract types.
  • 抽象クラスが許可されている (ただし必要ありません) に抽象メンバーを含めることができます。An abstract class is permitted (but not required) to contain abstract members.
  • 抽象クラスをシールドすることはできません。An abstract class cannot be sealed.

非抽象クラスは抽象クラスから派生するときに、非抽象クラスは、これらの抽象メンバーをオーバーライドするため、すべての継承抽象メンバーの実際の実装を含める必要があります。When a non-abstract class is derived from an abstract class, the non-abstract class must include actual implementations of all inherited abstract members, thereby overriding those abstract members. In the example

abstract class A
{
    public abstract void F();
}

abstract class B: A
{
    public void G() {}
}

class C: B
{
    public override void F() {
        // actual implementation of F
    }
}

抽象クラスA抽象メソッドを導入Fします。the abstract class A introduces an abstract method F. クラスBその他の方法が導入されましたGの実装を提供しないのでFBする必要がありますも抽象として宣言します。Class B introduces an additional method G, but since it doesn't provide an implementation of F, B must also be declared abstract. クラスCオーバーライドFし、実際の実装を提供します。Class C overrides F and provides an actual implementation. 抽象メンバーがないのでCC許可しました (ただし必要ありません) は非抽象にします。Since there are no abstract members in C, C is permitted (but not required) to be non-abstract.

シール クラスSealed classes

sealed修飾子がクラスからの派生を防ぐために使用します。The sealed modifier is used to prevent derivation from a class. シール クラスが別のクラスの基底クラスとして指定されている場合、コンパイル時エラーが発生します。A compile-time error occurs if a sealed class is specified as the base class of another class.

シール クラスには、抽象クラスにもできません。A sealed class cannot also be an abstract class.

sealed修飾子は、主に、意図しない派生を防ぐために使用しますが、特定のランタイム最適化こともできます。The sealed modifier is primarily used to prevent unintended derivation, but it also enables certain run-time optimizations. 具体的には、シール クラス、派生クラスが含まれないことがわかっているため、シール クラスのインスタンス上の仮想関数メンバーの呼び出しを非仮想呼び出しに変換することができます。In particular, because a sealed class is known to never have any derived classes, it is possible to transform virtual function member invocations on sealed class instances into non-virtual invocations.

静的クラスStatic classes

staticとして宣言するクラスをマークする修飾子を使用する静的クラスします。The static modifier is used to mark the class being declared as a static class. 静的クラスはインスタンス化できない型として使用することはできません、および静的メンバーのみを含めることができます。A static class cannot be instantiated, cannot be used as a type and can contain only static members. 静的クラスは、拡張メソッドの宣言を含めることができますのみ (拡張メソッド)。Only a static class can contain declarations of extension methods (Extension methods).

静的クラスの宣言では、次の制限を受けます。A static class declaration is subject to the following restrictions:

  • 静的クラスが含まない場合があります、sealedまたはabstract修飾子。A static class may not include a sealed or abstract modifier. ただし、静的クラスをインスタンス化されたかから派生することはできません、ために動作するシールと abstract の両方の場合とに注意してください。Note, however, that since a static class cannot be instantiated or derived from, it behaves as if it was both sealed and abstract.
  • 静的クラスが含まない場合があります、 class_base仕様 (クラスの基本仕様) し、基底クラスまたは実装されたインターフェイスのリストを明示的に指定できません。A static class may not include a class_base specification (Class base specification) and cannot explicitly specify a base class or a list of implemented interfaces. 静的クラスは、型から暗黙的に継承objectします。A static class implicitly inherits from type object.
  • 静的クラスは静的メンバーのみを含むことができます (静的メンバーとインスタンス メンバー)。A static class can only contain static members (Static and instance members). 定数と入れ子にされた型が静的メンバーとして分類されることに注意してください。Note that constants and nested types are classified as static members.
  • 静的クラスを持つメンバーを含めることはできませんprotectedまたはprotected internalアクセシビリティを宣言します。A static class cannot have members with protected or protected internal declared accessibility.

これらの制限に違反するコンパイル時エラーになります。It is a compile-time error to violate any of these restrictions.

静的クラスには、インスタンス コンス トラクターがありません。A static class has no instance constructors. インスタンス コンス トラクター、静的クラスでない既定のインスタンス コンス トラクターを宣言することはできません (既定のコンス トラクター) は、静的クラスを提供します。It is not possible to declare an instance constructor in a static class, and no default instance constructor (Default constructors) is provided for a static class.

静的クラスのメンバーが自動的に静的でないし、メンバーの宣言が明示的に含める必要があります、 static (定数と入れ子にされた型) を除く修飾子。The members of a static class are not automatically static, and the member declarations must explicitly include a static modifier (except for constants and nested types). クラスは、外部の静的クラス内で入れ子になって、ときに、入れ子になったクラスは静的クラス明示的に含まれていない限り、static修飾子。When a class is nested within a static outer class, the nested class is not a static class unless it explicitly includes a static modifier.

静的クラスの型を参照します。Referencing static class types

A namespace_or_type_name (Namespace と型の名前) で許可されている場合は、静的クラスを参照A namespace_or_type_name (Namespace and type names) is permitted to reference a static class if

  • Namespace_or_type_nameは、Tで、 namespace_or_type_nameフォームのT.I、またはThe namespace_or_type_name is the T in a namespace_or_type_name of the form T.I, or
  • Namespace_or_type_nameは、Tで、 typeof_expression (引数リスト1) フォームのtypeof(T)します。The namespace_or_type_name is the T in a typeof_expression (Argument lists1) of the form typeof(T).

A primary_expression (関数メンバー) で許可されている場合は、静的クラスを参照A primary_expression (Function members) is permitted to reference a static class if

他のコンテキストで静的クラスを参照すると、コンパイル時エラーになります。In any other context it is a compile-time error to reference a static class. エラー構成要素の型の基本クラスとして使用する静的クラスにはたとえば、(入れ子になった型) のメンバー、ジェネリック型引数、または型パラメーターの制約。For example, it is an error for a static class to be used as a base class, a constituent type (Nested types) of a member, a generic type argument, or a type parameter constraint. 同様に、配列型、ポインター型で静的クラスは使用できません、 new 、キャスト式、式、is式、as式、sizeof式、または既定値の式。Likewise, a static class cannot be used in an array type, a pointer type, a new expression, a cast expression, an is expression, an as expression, a sizeof expression, or a default value expression.

Partial 識別子Partial modifier

partial修飾子を示すために使用されるこのclass_declaration部分型の宣言です。The partial modifier is used to indicate that this class_declaration is a partial type declaration. 指定された規則に従って、それを囲む名前空間または型の宣言内で同じ名前の複数の部分型の宣言は、フォームの 1 つの型宣言に結合、部分型します。Multiple partial type declarations with the same name within an enclosing namespace or type declaration combine to form one type declaration, following the rules specified in Partial types.

プログラムのテキストのセグメントを個別に分散クラスの宣言は、これらのセグメントを生成または別のコンテキスト内に保持する場合役立ちます。Having the declaration of a class distributed over separate segments of program text can be useful if these segments are produced or maintained in different contexts. たとえば、クラス宣言の 1 つの部分可能性がありますコンピューターによって生成されると、一方は手動で作成した他の。For instance, one part of a class declaration may be machine generated, whereas the other is manually authored. 2 つのテキストの分離は、他の更新と衝突する 1 つを更新プログラムを抑止します。Textual separation of the two prevents updates by one from conflicting with updates by the other.

型パラメーターType parameters

型パラメーターは、構築された型を作成する指定された型引数のプレース ホルダーを示す単純な識別子です。A type parameter is a simple identifier that denotes a placeholder for a type argument supplied to create a constructed type. 型パラメーターは、後で提供される型の正式なプレース ホルダーです。A type parameter is a formal placeholder for a type that will be supplied later. 一方、型引数 (引数を入力) が構築された型が作成されるときに、型パラメーターを置き換える実際の型。By contrast, a type argument (Type arguments) is the actual type that is substituted for the type parameter when a constructed type is created.

type_parameter_list
    : '<' type_parameters '>'
    ;

type_parameters
    : attributes? type_parameter
    | type_parameters ',' attributes? type_parameter
    ;

type_parameter
    : identifier
    ;

クラス宣言で型パラメーターごとの宣言領域に名前を定義します (宣言) そのクラスの。Each type parameter in a class declaration defines a name in the declaration space (Declarations) of that class. そのため、別の型パラメーターと同じ名前を持つことはできませんまたはメンバーがそのクラスで宣言します。Thus, it cannot have the same name as another type parameter or a member declared in that class. 型パラメーターには、型自体と同じ名前を持つことはできません。A type parameter cannot have the same name as the type itself.

クラスの基本仕様Class base specification

クラス宣言を含めることができます、 class_baseクラスとインターフェイスの直接基底クラスを定義する仕様 (インターフェイス) 直接クラスによって実装されます。A class declaration may include a class_base specification, which defines the direct base class of the class and the interfaces (Interfaces) directly implemented by the class.

class_base
    : ':' class_type
    | ':' interface_type_list
    | ':' class_type ',' interface_type_list
    ;

interface_type_list
    : interface_type (',' interface_type)*
    ;

クラス宣言で指定された基本クラスは、構築済みクラス型を指定できます (構築型)。The base class specified in a class declaration can be a constructed class type (Constructed types). スコープ内の型パラメーターを伴うことができますが、基底クラスは、独自の型パラメーターにすることはできません。A base class cannot be a type parameter on its own, though it can involve the type parameters that are in scope.

class Extend<V>: V {}            // Error, type parameter used as base class

基底クラスBase classes

ときに、 class_typeに含まれている、 class_base、宣言されたクラスの直接の基本クラスを指定します。When a class_type is included in the class_base, it specifies the direct base class of the class being declared. クラス宣言がにない場合class_base、または、 class_baseリストのみインターフェイスの種類、直接基底クラスがあると見なされますobjectします。If a class declaration has no class_base, or if the class_base lists only interface types, the direct base class is assumed to be object. 」の説明に従って、クラスの直接の基本クラスからの継承メンバー継承します。A class inherits members from its direct base class, as described in Inheritance.

In the example

class A {}

class B: A {}

クラスAの直接基底クラスと呼ばれますB、およびBから派生する言いますAします。class A is said to be the direct base class of B, and B is said to be derived from A. Aは直接基底クラスを明示的に指定、その直接の基本クラスが暗黙的にobjectします。Since A does not explicitly specify a direct base class, its direct base class is implicitly object.

構築済みクラス型では、ジェネリック クラスの宣言で基底クラスが指定されている場合、構築された型の基本クラスを取得、ごとに置き換えることによってtype_parameter対応する基本クラスの宣言でtype_argument構築された型のです。For a constructed class type, if a base class is specified in the generic class declaration, the base class of the constructed type is obtained by substituting, for each type_parameter in the base class declaration, the corresponding type_argument of the constructed type. ジェネリック クラス宣言Given the generic class declarations

class B<U,V> {...}

class G<T>: B<string,T[]> {...}

構築された型の基本クラスG<int>なりますB<string,int[]>します。the base class of the constructed type G<int> would be B<string,int[]>.

クラス型の直接の基本クラスは、少なくとも、クラス型自体と同程度にアクセスである必要があります (アクセシビリティ ドメイン)。The direct base class of a class type must be at least as accessible as the class type itself (Accessibility domains). などのコンパイル時エラーは、publicクラスから派生する、privateまたはinternalクラス。For example, it is a compile-time error for a public class to derive from a private or internal class.

クラス型の直接の基本クラスでは、次の種類のいずれかのある必要がありますいない: System.ArraySystem.DelegateSystem.MulticastDelegateSystem.Enum、またはSystem.ValueTypeします。The direct base class of a class type must not be any of the following types: System.Array, System.Delegate, System.MulticastDelegate, System.Enum, or System.ValueType. ジェネリック クラス宣言をさらに、使用することはできませんSystem.Attribute直接的または間接的な基底クラスとして。Furthermore, a generic class declaration cannot use System.Attribute as a direct or indirect base class.

直接基底クラスの指定の意味を決定する際にAクラスのB、直接の基本クラスのBは一時的にあると見なされますobjectします。While determining the meaning of the direct base class specification A of a class B, the direct base class of B is temporarily assumed to be object. 基底クラスの指定の意味が再帰的にことはできません、直感的にこれにより、それ自体に依存します。Intuitively this ensures that the meaning of a base class specification cannot recursively depend on itself. 例:The example:

class A<T> {
   public class B {}
}

class C : A<C.B> {}

以降、基底クラスの指定でのエラーでは、A<C.B>の直接の基本クラスCと見なされますobject、ため、(のルールによってNamespace と型の名前)Cと見なされないメンバーを持つBします。is in error since in the base class specification A<C.B> the direct base class of C is considered to be object, and hence (by the rules of Namespace and type names) C is not considered to have a member B.

クラス型の基底クラスは、直接基底クラスとその基本クラスです。The base classes of a class type are the direct base class and its base classes. つまり、基本クラスのセットは、直接基底クラスの関係の推移閉包です。In other words, the set of base classes is the transitive closure of the direct base class relationship. 上記の基本クラスの例を参照するBAobjectします。Referring to the example above, the base classes of B are A and object. In the example

class A {...}

class B<T>: A {...}

class C<T>: B<IComparable<T>> {...}

class D<T>: C<T[]> {...}

基本クラスD<int>C<int[]>B<IComparable<int[]>>A、およびobjectします。the base classes of D<int> are C<int[]>, B<IComparable<int[]>>, A, and object.

クラスを除くobject、すべてのクラス型が正確に 1 つの直接基底クラス。Except for class object, every class type has exactly one direct base class. objectクラスの直接基底クラスを持たないし、他のすべてのクラスの最終的な基底クラスです。The object class has no direct base class and is the ultimate base class of all other classes.

クラスとBクラスから派生するA、コンパイル時エラーにはAに依存するBします。When a class B derives from a class A, it is a compile-time error for A to depend on B. クラスに直接依存(あれば) 直接基本クラスとに直接依存はすぐに入れ子になっている (あれば) クラス。A class directly depends on its direct base class (if any) and directly depends on the class within which it is immediately nested (if any). この定義を指定するには、クラスが依存しているクラスの完全なセットがの再帰的、および推移的なクロージャ、に直接依存リレーションシップ。Given this definition, the complete set of classes upon which a class depends is the reflexive and transitive closure of the directly depends on relationship.

例では、The example

class A: A {}

誤ったクラスは、自身に依存しているためです。is erroneous because the class depends on itself. 例では、同様に、Likewise, the example

class A: B {}
class B: C {}
class C: A {}

クラスは、循環的自体に依存するためにはエラーです。is in error because the classes circularly depend on themselves. 例では、最後に、Finally, the example

class A: B.C {}

class B: A
{
    public class C {}
}

ため、コンパイル時エラー結果Aに依存B.C(直接基底クラス) に依存するB(すぐ外側のクラス) に依存する循環的Aresults in a compile-time error because A depends on B.C (its direct base class), which depends on B (its immediately enclosing class), which circularly depends on A.

クラスは、内部に入れ子になっているクラスに依存しないことに注意してください。Note that a class does not depend on the classes that are nested within it. In the example

class A
{
    class B: A {}
}

B 依存A(ためAは、直接基底クラスとそのすぐ外側のクラスの両方) がAに依存しないB(ためBは基底クラスでも、外側のクラスのA).B depends on A (because A is both its direct base class and its immediately enclosing class), but A does not depend on B (since B is neither a base class nor an enclosing class of A). そのため、この例では有効です。Thus, the example is valid.

派生することはできません、sealedクラス。It is not possible to derive from a sealed class. In the example

sealed class A {}

class B: A {}            // Error, cannot derive from a sealed class

クラスBしようとするから派生するために、エラーでは、sealedクラスAします。class B is in error because it attempts to derive from the sealed class A.

インターフェイスの実装Interface implementations

A class_base仕様は場合、クラスが言います、特定のインターフェイス型を直接実装するインターフェイスの型の一覧を含めることができます。A class_base specification may include a list of interface types, in which case the class is said to directly implement the given interface types. インターフェイスの実装については、説明でさらにインターフェイスの実装します。Interface implementations are discussed further in Interface implementations.

型パラメーターの制約Type parameter constraints

ジェネリック型、メソッドの宣言を含めることで型パラメーターの制約を指定できます必要に応じてtype_parameter_constraints_clause秒。Generic type and method declarations can optionally specify type parameter constraints by including type_parameter_constraints_clauses.

type_parameter_constraints_clause
    : 'where' type_parameter ':' type_parameter_constraints
    ;

type_parameter_constraints
    : primary_constraint
    | secondary_constraints
    | constructor_constraint
    | primary_constraint ',' secondary_constraints
    | primary_constraint ',' constructor_constraint
    | secondary_constraints ',' constructor_constraint
    | primary_constraint ',' secondary_constraints ',' constructor_constraint
    ;

primary_constraint
    : class_type
    | 'class'
    | 'struct'
    ;

secondary_constraints
    : interface_type
    | type_parameter
    | secondary_constraints ',' interface_type
    | secondary_constraints ',' type_parameter
    ;

constructor_constraint
    : 'new' '(' ')'
    ;

type_parameter_constraints_clauseトークンから成るwhere後に、型パラメーターの名前の後にコロンとその型パラメーターの制約の一覧。Each type_parameter_constraints_clause consists of the token where, followed by the name of a type parameter, followed by a colon and the list of constraints for that type parameter. 最大で 1 つできますwhere型パラメーターごとに、句、where句は、任意の順序で表示できます。There can be at most one where clause for each type parameter, and the where clauses can be listed in any order. ように、getsetプロパティのアクセサー内のトークン、whereトークンは、キーワードではありません。Like the get and set tokens in a property accessor, the where token is not a keyword.

指定された制約の一覧をwhere句は、次のコンポーネントのいずれかをこの順序で含めることができます。 1 つの主な制約、1 つまたは複数のセカンダリ制約、およびコンス トラクターの制約new()します。The list of constraints given in a where clause can include any of the following components, in this order: a single primary constraint, one or more secondary constraints, and the constructor constraint, new().

主な制約は、クラス型を指定できますまたは参照型制約classまたは値の型の制約 structA primary constraint can be a class type or the reference type constraint class or the value type constraint struct. セカンダリの制約として使用できる、 type_parameterまたはinterface_typeします。A secondary constraint can be a type_parameter or interface_type.

参照型の制約では、型パラメーターを使用する型引数は参照型である必要がありますを指定します。The reference type constraint specifies that a type argument used for the type parameter must be a reference type. すべてのクラス型、インターフェイス型、デリゲート型、配列型、および (下記を参照) のように、参照型に既知の型パラメーターは、この制約を満たしています。All class types, interface types, delegate types, array types, and type parameters known to be a reference type (as defined below) satisfy this constraint.

値型の制約では、型パラメーターを使用する型引数は null 非許容値型である必要がありますを指定します。The value type constraint specifies that a type argument used for the type parameter must be a non-nullable value type. すべての null 非許容の構造体型、列挙型、および値型の制約を持つ型パラメーターは、この制約を満たしています。All non-nullable struct types, enum types, and type parameters having the value type constraint satisfy this constraint. 値型、null 許容型に分類されますが (null 許容型) 値の型の制約を満たしていません。Note that although classified as a value type, a nullable type (Nullable types) does not satisfy the value type constraint. 値型の制約を持つ型パラメーターも含めることはできません、 constructor_constraintします。A type parameter having the value type constraint cannot also have the constructor_constraint.

ポインター型では、型引数を許可しないと、参照型または値型のいずれかの制約を満たすためには考慮されません。Pointer types are never allowed to be type arguments and are not considered to satisfy either the reference type or value type constraints.

クラス型、インターフェイス型または型パラメーター制約とは、その型は最小限に抑える「ベース型」型パラメーターに使用されるすべての型引数をサポートする必要がありますを指定します。If a constraint is a class type, an interface type, or a type parameter, that type specifies a minimal "base type" that every type argument used for that type parameter must support. 構築された型またはジェネリック メソッドを使用すると、型引数がコンパイル時に型パラメーターに対する制約に照らしてチェックします。Whenever a constructed type or generic method is used, the type argument is checked against the constraints on the type parameter at compile-time. 指定された型引数で説明する条件を満たす必要があります制約条件を満たすします。The type argument supplied must satisfy the conditions described in Satisfying constraints.

A class_type制約は、次の規則を満たす必要があります。A class_type constraint must satisfy the following rules:

  • 種類は、クラス型である必要があります。The type must be a class type.
  • 型でなければなりませんsealedします。The type must not be sealed.
  • 型は、次の種類のいずれかを指定しない必要があります: System.ArraySystem.DelegateSystem.Enum、またはSystem.ValueTypeします。The type must not be one of the following types: System.Array, System.Delegate, System.Enum, or System.ValueType.
  • 型でなければなりませんobjectします。The type must not be object. すべての型が派生するためobject、このような制約は効果がありませんが、許可された場合。Because all types derive from object, such a constraint would have no effect if it were permitted.
  • 特定の型パラメーターを最大で 1 つの制約は、クラス型であることができます。At most one constraint for a given type parameter can be a class type.

として指定された型、 interface_type制約は、次の規則を満たす必要があります。A type specified as an interface_type constraint must satisfy the following rules:

  • 型はインターフェイス型である必要があります。The type must be an interface type.
  • 複数回に指定されていない型もする必要がありますを指定したwhere句。A type must not be specified more than once in a given where clause.

いずれの場合も、制約は、関連付けられている型または構築された型の一部として、メソッドの宣言の型パラメーターのいずれかが含まれることができ、宣言された型が含まれることができます。In either case, the constraint can involve any of the type parameters of the associated type or method declaration as part of a constructed type, and can involve the type being declared.

型パラメーターの制約は、少なくともにアクセスする必要がありますを指定したクラスまたはインターフェイスの型 (アクセシビリティ制約) ジェネリック型またはメソッドが宣言されているとします。Any class or interface type specified as a type parameter constraint must be at least as accessible (Accessibility constraints) as the generic type or method being declared.

として指定された型、 type_parameter制約は、次の規則を満たす必要があります。A type specified as a type_parameter constraint must satisfy the following rules:

  • 種類は、型パラメーターである必要があります。The type must be a type parameter.
  • 複数回に指定されていない型もする必要がありますを指定したwhere句。A type must not be specified more than once in a given where clause.

さらにはならないサイクルによって定義されている推移的な関係の依存関係のある、型パラメーターの依存関係グラフ。In addition there must be no cycles in the dependency graph of type parameters, where dependency is a transitive relation defined by:

  • 場合、型パラメーターT型パラメーターを制約として使用SS異なりますTします。If a type parameter T is used as a constraint for type parameter S then S depends on T.
  • 場合、型パラメーターS型パラメーターに依存TT型パラメーターに依存US異なります UIf a type parameter S depends on a type parameter T and T depends on a type parameter U then S depends on U.

この関係がある、(直接または間接的に)、それ自体に依存する型パラメーターのコンパイル時エラーになります。Given this relation, it is a compile-time error for a type parameter to depend on itself (directly or indirectly).

すべての制約は、依存する型パラメーターの間で一貫性のあるである必要があります。Any constraints must be consistent among dependent type parameters. 場合のパラメーターを入力S型パラメーターに依存Tし。If type parameter S depends on type parameter T then:

  • T 値型の制約が必要ありません。T must not have the value type constraint. それ以外の場合、Tこれは実質的にシールSと同じ型にすることが強制されますT、2 つの型パラメーターでは必要はありません。Otherwise, T is effectively sealed so S would be forced to be the same type as T, eliminating the need for two type parameters.
  • 場合Sしの値の型の制約を持つTは必要ありません、 class_type制約。If S has the value type constraint then T must not have a class_type constraint.
  • 場合Sが、 class_type制約ATが、 class_type制約B恒等変換が存在する必要がありますまたは暗黙的な参照変換からABから暗黙の参照変換またはBAします。If S has a class_type constraint A and T has a class_type constraint B then there must be an identity conversion or implicit reference conversion from A to B or an implicit reference conversion from B to A.
  • 場合S型パラメーターにも依存UUが、 class_type制約ATが、 class_type制約B恒等変換またはからの暗黙的な参照変換がある必要がありますし、ABから暗黙の参照変換またはBAします。If S also depends on type parameter U and U has a class_type constraint A and T has a class_type constraint B then there must be an identity conversion or implicit reference conversion from A to B or an implicit reference conversion from B to A.

それが有効でSが値型の制約とT参照型の制約にします。It is valid for S to have the value type constraint and T to have the reference type constraint. これを効果的に制限T型にSystem.ObjectSystem.ValueTypeSystem.Enum、および任意のインターフェイス型。Effectively this limits T to the types System.Object, System.ValueType, System.Enum, and any interface type.

場合、where句型パラメーターにはにコンス トラクターの制約が含まれています (フォームを持つnew()) を使用することは、new演算子、型のインスタンスを作成する (オブジェクト作成式).If the where clause for a type parameter includes a constructor constraint (which has the form new()), it is possible to use the new operator to create instances of the type (Object creation expressions). 使用する型引数が値型の制約またはコンス トラクターの制約 (参照型パラメーターまたは型パラメーターでは、コンス トラクター制約する必要があります (このコンス トラクターは任意の値型に暗黙的に存在する) のパブリック コンス トラクターを指定することパラメーターの制約入力詳細については)。Any type argument used for a type parameter with a constructor constraint must have a public parameterless constructor (this constructor implicitly exists for any value type) or be a type parameter having the value type constraint or constructor constraint (see Type parameter constraints for details).

制約の例を次に示します。The following are examples of constraints:

interface IPrintable
{
    void Print();
}

interface IComparable<T>
{
    int CompareTo(T value);
}

interface IKeyProvider<T>
{
    T GetKey();
}

class Printer<T> where T: IPrintable {...}

class SortedList<T> where T: IComparable<T> {...}

class Dictionary<K,V>
    where K: IComparable<K>
    where V: IPrintable, IKeyProvider<K>, new()
{
    ...
}

次の例は、型パラメーターの依存関係グラフで循環が発生しているために、エラーには。The following example is in error because it causes a circularity in the dependency graph of the type parameters:

class Circular<S,T>
    where S: T
    where T: S                // Error, circularity in dependency graph
{
    ...
}

次の例では、その他の無効な状況を示します。The following examples illustrate additional invalid situations:

class Sealed<S,T>
    where S: T
    where T: struct        // Error, T is sealed
{
    ...
}

class A {...}

class B {...}

class Incompat<S,T>
    where S: A, T
    where T: B                // Error, incompatible class-type constraints
{
    ...
}

class StructWithClass<S,T,U>
    where S: struct, T
    where T: U
    where U: A                // Error, A incompatible with struct
{
    ...
}

実質的な基本クラス型パラメーターのTが次のように定義されています。The effective base class of a type parameter T is defined as follows:

  • 場合Tprimary 制約がない場合や、その効果的な基底クラスの型パラメーター制約がobjectします。If T has no primary constraints or type parameter constraints, its effective base class is object.
  • 場合T値型の制約、その効果的な基底クラスはSystem.ValueTypeします。If T has the value type constraint, its effective base class is System.ValueType.
  • 場合Tが、 class_type制約Ctype_parameter制約、その効果的な基底クラスはCします。If T has a class_type constraint C but no type_parameter constraints, its effective base class is C.
  • 場合Tにないclass_type制約が、1 つまたは複数type_parameter制約、その効果的な基底クラスは、最も内側の型 (リフトの変換演算子) の有効な基本クラスのセットでそのtype_parameter制約。If T has no class_type constraint but has one or more type_parameter constraints, its effective base class is the most encompassed type (Lifted conversion operators) in the set of effective base classes of its type_parameter constraints. 一貫性規則では、このような最も内側の型が存在することを確認します。The consistency rules ensure that such a most encompassed type exists.
  • 場合T両方を持つ、 class_type制約と 1 つ以上type_parameter制約、その効果的な基底クラスは、最も内側の型 (リフトの変換演算子) から成るセットで、 class_typeの制約Tの効果的な基底クラスとそのtype_parameter制約。If T has both a class_type constraint and one or more type_parameter constraints, its effective base class is the most encompassed type (Lifted conversion operators) in the set consisting of the class_type constraint of T and the effective base classes of its type_parameter constraints. 一貫性規則では、このような最も内側の型が存在することを確認します。The consistency rules ensure that such a most encompassed type exists.
  • 場合Tを持ち、参照型の制約はいいえclass_type制約、その効果的な基底クラスはobjectします。If T has the reference type constraint but no class_type constraints, its effective base class is object.

T に制約がある場合、これらの規則の目的でVつまり、 value_type、代わりに最も固有の基本型のVは、 class_typeします。For the purpose of these rules, if T has a constraint V that is a value_type, use instead the most specific base type of V that is a class_type. これは、明示的に特定の制約では発生しないことができますが、ジェネリック メソッドの制約は、オーバーライドするメソッドの宣言または明示的なインターフェイス メソッドの実装によって暗黙的に継承されたときに発生する可能性があります。This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method.

これらの規則は、有効な基本クラスが常にあることを確認、 class_typeします。These rules ensure that the effective base class is always a class_type.

有効なインターフェイス セット型パラメーターのTが次のように定義されています。The effective interface set of a type parameter T is defined as follows:

  • 場合Tにないsecondary_constraints、その有効なインターフェイス セットが空です。If T has no secondary_constraints, its effective interface set is empty.
  • 場合Tinterface_type制約がないtype_parameter制約、その有効なインターフェイス セットが一連のinterface_type制約。If T has interface_type constraints but no type_parameter constraints, its effective interface set is its set of interface_type constraints.
  • 場合Tにないinterface_type制約が、 type_parameter制約、その有効なインターフェイス セットがの有効なインターフェイスのセットの和集合の種類パラメーター制約。If T has no interface_type constraints but has type_parameter constraints, its effective interface set is the union of the effective interface sets of its type_parameter constraints.
  • 場合T両方interface_type制約とtype_parameter制約、その有効なインターフェイス セットがそのセットの和集合interface_type制約との有効なインターフェイス セットをそのtype_parameter制約。If T has both interface_type constraints and type_parameter constraints, its effective interface set is the union of its set of interface_type constraints and the effective interface sets of its type_parameter constraints.

型パラメーターが参照型に既知の参照型の制約があるかどうか、または、有効な基本クラスがobjectまたはSystem.ValueTypeします。A type parameter is known to be a reference type if it has the reference type constraint or its effective base class is not object or System.ValueType.

制約付きの型パラメーターの型の値は、制約によって暗黙的にインスタンス メンバーへのアクセスに使用できます。Values of a constrained type parameter type can be used to access the instance members implied by the constraints. In the example

interface IPrintable
{
    void Print();
}

class Printer<T> where T: IPrintable
{
    void PrintOne(T x) {
        x.Print();
    }
}

メソッドIPrintable上で直接呼び出すことができますxためTが常に実装するために制約IPrintableします。the methods of IPrintable can be invoked directly on x because T is constrained to always implement IPrintable.

クラス本体Class body

Class_bodyクラスのクラスのメンバーを定義します。The class_body of a class defines the members of that class.

class_body
    : '{' class_member_declaration* '}'
    ;

部分型Partial types

型宣言を複数に分割できるようにする部分型の宣言します。A type declaration can be split across multiple partial type declarations. 型宣言は、当該プログラムのコンパイル時と実行時の処理の残りの部分の中に 1 つの宣言として扱われます、このセクションでは、規則に従っての部分から構成されます。The type declaration is constructed from its parts by following the rules in this section, whereupon it is treated as a single declaration during the remainder of the compile-time and run-time processing of the program.

A class_declarationstruct_declarationまたはinterface_declarationが含まれる場合は、部分型の宣言を表す、partial修飾子。A class_declaration, struct_declaration or interface_declaration represents a partial type declaration if it includes a partial modifier. partial キーワードでないし、キーワードのいずれかの直前に表示される場合、修飾子としてのみ機能classstructまたはinterface型宣言、または型の前にvoidメソッドの宣言でします。partial is not a keyword, and only acts as a modifier if it appears immediately before one of the keywords class, struct or interface in a type declaration, or before the type void in a method declaration. 他のコンテキストで、通常の識別子として使用できます。In other contexts it can be used as a normal identifier.

部分型の宣言の各部分を含める必要があります、partial修飾子。Each part of a partial type declaration must include a partial modifier. 同じ名前を指定する必要があり、同じ名前空間または型の他の部分宣言で宣言します。It must have the same name and be declared in the same namespace or type declaration as the other parts. partial修飾子は、型宣言の追加部分が別の場所に存在してもこのようなその他の部分が存在することが必須ではないことを示します。 1 つの宣言を持つ型を含めることは、partial修飾子。The partial modifier indicates that additional parts of the type declaration may exist elsewhere, but the existence of such additional parts is not a requirement; it is valid for a type with a single declaration to include the partial modifier.

1 つの型宣言に、コンパイル時に、パーツをマージできるように、部分型のすべての部分を一緒にコンパイルする必要があります。All parts of a partial type must be compiled together such that the parts can be merged at compile-time into a single type declaration. 具体的には、部分型には既にコンパイルされている型を拡張することはできません。Partial types specifically do not allow already compiled types to be extended.

使用して複数の部分に入れ子にされた型を宣言することがあります、partial修飾子。Nested types may be declared in multiple parts by using the partial modifier. 通常、含んでいる型が宣言を使用してpartial良好であり、入れ子にされた型の各部分を含んでいる型の別の部分で宣言したので。Typically, the containing type is declared using partial as well, and each part of the nested type is declared in a different part of the containing type.

partialデリゲートまたは列挙型の宣言に修飾子は許可されていません。The partial modifier is not permitted on delegate or enum declarations.

属性Attributes

部分型の属性は、各部分の属性を不特定の順序で組み合わせることで決定されます。The attributes of a partial type are determined by combining, in an unspecified order, the attributes of each of the parts. 属性は、複数の部分に配置する場合は、型の属性を複数回指定すると同じです。If an attribute is placed on multiple parts, it is equivalent to specifying the attribute multiple times on the type. たとえば、2 つの部分があると:For example, the two parts:

[Attr1, Attr2("hello")]
partial class A {}

[Attr3, Attr2("goodbye")]
partial class A {}

などの宣言に同等です。are equivalent to a declaration such as:

[Attr1, Attr2("hello"), Attr3, Attr2("goodbye")]
class A {}

型パラメーターの属性は、同様の方法で結合します。Attributes on type parameters combine in a similar fashion.

修飾子Modifiers

部分型の宣言がアクセシビリティの指定が含まれてとき (、 publicprotectedinternal、およびprivate修飾子)、アクセシビリティの仕様が含まれるその他のすべての部分に同意する必要があります。When a partial type declaration includes an accessibility specification (the public, protected, internal, and private modifiers) it must agree with all other parts that include an accessibility specification. アクセシビリティの指定を含む、部分的な型の部分がない場合、型が指定された適切な既定のアクセシビリティ (宣言されたアクセシビリティ)。If no part of a partial type includes an accessibility specification, the type is given the appropriate default accessibility (Declared accessibility).

入れ子にされた型の 1 つまたは複数の部分宣言が含まれる場合、new修飾子は、入れ子にされた型が継承されたメンバーを非表示にする場合に警告が報告されません (継承による隠ぺい)。If one or more partial declarations of a nested type include a new modifier, no warning is reported if the nested type hides an inherited member (Hiding through inheritance).

クラスの 1 つまたは複数の部分宣言が含まれる場合、abstract修飾子、クラスが抽象と見なされます (抽象クラス)。If one or more partial declarations of a class include an abstract modifier, the class is considered abstract (Abstract classes). それ以外の場合、クラスは、非抽象と見なされます。Otherwise, the class is considered non-abstract.

クラスの 1 つまたは複数の部分宣言が含まれる場合、sealed修飾子、クラスがシールと見なされます (クラスをシール)。If one or more partial declarations of a class include a sealed modifier, the class is considered sealed (Sealed classes). クラスを考慮する場合は、封印されていません。Otherwise, the class is considered unsealed.

クラスを abstract と sealed の両方ができないことに注意してください。Note that a class cannot be both abstract and sealed.

ときに、unsafeその特定の部分は、unsafe コンテキストと見なされるのみ、部分型の宣言に修飾子が使用されます (Unsafe コンテキスト)。When the unsafe modifier is used on a partial type declaration, only that particular part is considered an unsafe context (Unsafe contexts).

型パラメーターと制約Type parameters and constraints

ジェネリック型が複数の部分で宣言されている場合、型パラメーターが各部分に記述する必要があります。If a generic type is declared in multiple parts, each part must state the type parameters. 各部分は、順番、型パラメーターのと同じ数と型パラメーターごとに、同じ名前が必要です。Each part must have the same number of type parameters, and the same name for each type parameter, in order.

部分的なジェネリック型の宣言が制約が含まれる場合 (where句)、制約は制約を含むその他のすべての部分と一致する必要があります。When a partial generic type declaration includes constraints (where clauses), the constraints must agree with all other parts that include constraints. 具体的には、制約が含まれる各の部分は、型パラメーターの同じセットに対して制約を持つ必要があり、型パラメーターごとのプライマリ、セカンダリ、およびコンス トラクター制約必要がありますと同じです。Specifically, each part that includes constraints must have constraints for the same set of type parameters, and for each type parameter the sets of primary, secondary, and constructor constraints must be equivalent. 制約の 2 つのセットは、同じメンバーが含まれている場合に相当します。Two sets of constraints are equivalent if they contain the same members. 部分的なジェネリック型の一部は、型パラメーターの制約がないを指定します、パラメーターと見なされる型は無制限です。If no part of a partial generic type specifies type parameter constraints, the type parameters are considered unconstrained.

例では、The example

partial class Dictionary<K,V>
    where K: IComparable<K>
    where V: IKeyProvider<K>, IPersistable
{
    ...
}

partial class Dictionary<K,V>
    where V: IPersistable, IKeyProvider<K>
    where K: IComparable<K>
{
    ...
}

partial class Dictionary<K,V>
{
    ...
}

正しい効果的に制約 (最初の 2 つ) を含む部分が同じセカンダリをプライマリのセットと同じ型パラメーターでは、一連のコンス トラクターの制約を指定するためです。is correct because those parts that include constraints (the first two) effectively specify the same set of primary, secondary, and constructor constraints for the same set of type parameters, respectively.

基底クラスBase class

部分クラス宣言には、基底クラスの指定が含まれています。 基底クラスの指定を含むその他のすべての部分を持つことに同意する必要があります。When a partial class declaration includes a base class specification it must agree with all other parts that include a base class specification. 部分クラスの一部に基底クラスの指定が含まれていない場合、基本クラスは次のようになります。 System.Object (基底クラス)。If no part of a partial class includes a base class specification, the base class becomes System.Object (Base classes).

基底インターフェイスBase interfaces

複数の部分で宣言された型の基本インターフェイスのセットは、各部分で指定された基本インターフェイスの和集合です。The set of base interfaces for a type declared in multiple parts is the union of the base interfaces specified on each part. 各部分では、1 回にという名前のみ、特定の基本インターフェイスも可能性がありますが、同じ基本インターフェイスの名前を複数の部分のことができます。A particular base interface may only be named once on each part, but it is permitted for multiple parts to name the same base interface(s). 任意の基本インターフェイスのメンバーの実装の 1 つだけあります。There must only be one implementation of the members of any given base interface.

In the example

partial class C: IA, IB {...}

partial class C: IC {...}

partial class C: IA, IB {...}

クラスの基本インターフェイスのセットCIAIB、およびICします。the set of base interfaces for class C is IA, IB, and IC.

通常、各部分はその部分で宣言されたインターフェイスの実装を提供します。ただし、これは要件ではありません。Typically, each part provides an implementation of the interface(s) declared on that part; however, this is not a requirement. 一部は、別の部分で宣言されたインターフェイスの実装を提供できます。A part may provide the implementation for an interface declared on a different part:

partial class X
{
    int IComparable.CompareTo(object o) {...}
}

partial class X: IComparable
{
    ...
}

メンバーMembers

部分メソッドを除く (部分メソッド)、複数の部分で宣言された型のメンバーのセットは、各部分で宣言されたメンバーのセットの和集合だけです。With the exception of partial methods (Partial methods), the set of members of a type declared in multiple parts is simply the union of the set of members declared in each part. 型宣言のすべての部分の本文が同じ宣言領域を共有 (宣言)、および各メンバーのスコープ (スコープ) に、すべての部分の本文を拡張します。The bodies of all parts of the type declaration share the same declaration space (Declarations), and the scope of each member (Scopes) extends to the bodies of all the parts. 任意のメンバーのアクセシビリティ ドメインは、外側の型のすべての部分を常に含まれますprivate 1 つの部分で宣言されたメンバーは、別の部分から自由にアクセスします。The accessibility domain of any member always includes all the parts of the enclosing type; a private member declared in one part is freely accessible from another part. そのメンバーが持つ型でない限り、型の 1 つ以上の部分で同じメンバーを宣言すると、コンパイル時エラーは、partial修飾子。It is a compile-time error to declare the same member in more than one part of the type, unless that member is a type with the partial modifier.

partial class A
{
    int x;                     // Error, cannot declare x more than once

    partial class Inner        // Ok, Inner is a partial type
    {
        int y;
    }
}

partial class A
{
    int x;                     // Error, cannot declare x more than once

    partial class Inner        // Ok, Inner is a partial type
    {
        int z;
    }
}

型内のメンバーの順序が、c# のコードをほとんど重要では、他の言語や環境とやり取りするときに大きな可能性があります。The ordering of members within a type is rarely significant to C# code, but may be significant when interfacing with other languages and environments. このような場合は、複数の部分で宣言された型内のメンバーの順序は定義されません。In these cases, the ordering of members within a type declared in multiple parts is undefined.

部分メソッドPartial methods

部分メソッドは、型宣言の 1 つの部分で定義されているし、別に実装できます。Partial methods can be defined in one part of a type declaration and implemented in another. 実装は省略可能です。部分メソッドを実装部分がない場合、すべての呼び出しと部分メソッド宣言は、部分の組み合わせから作成される型の宣言から削除されます。The implementation is optional; if no part implements the partial method, the partial method declaration and all calls to it are removed from the type declaration resulting from the combination of the parts.

部分メソッドは、アクセス修飾子を定義することはできませんが、暗黙的にprivateします。Partial methods cannot define access modifiers, but are implicitly private. 戻り値の型である必要がありますvoid、そのパラメーターを持つことができません、out修飾子。Their return type must be void, and their parameters cannot have the out modifier. 識別子partial直前に表示される場合にのみは、特殊なメソッドの宣言でキーワードとして認識、void型。 それ以外の場合、通常の識別子として使用できますが。The identifier partial is recognized as a special keyword in a method declaration only if it appears right before the void type; otherwise it can be used as a normal identifier. 部分メソッドは、インターフェイス メソッドを明示的に実装できません。A partial method cannot explicitly implement interface methods.

部分メソッド宣言の 2 つの種類があります。メソッド宣言の本体がセミコロンの場合は、宣言と呼ばれます、部分メソッドの宣言を定義するします。There are two kinds of partial method declarations: If the body of the method declaration is a semicolon, the declaration is said to be a defining partial method declaration. として本文を指定した場合、ブロック、宣言はモード、実装部分メソッド宣言します。If the body is given as a block, the declaration is said to be an implementing partial method declaration. 型宣言の部分があります指定されたシグネチャを持つ部分メソッド宣言を定義する 1 つだけと実装、特定のシグネチャを持つ部分メソッド宣言は 1 つのみです。Across the parts of a type declaration there can be only one defining partial method declaration with a given signature, and there can be only one implementing partial method declaration with a given signature. 部分メソッドの実装宣言が指定された、対応する部分メソッド宣言の定義が存在する必要がありますとして宣言する必要がありますと一致する場合は、次に指定します。If an implementing partial method declaration is given, a corresponding defining partial method declaration must exist, and the declarations must match as specified in the following:

  • 宣言は、(が必ずしも同じ順序で)、同じ修飾子を設定する必要があります、メソッド名、型パラメーターの数、およびパラメーターの数。The declarations must have the same modifiers (although not necessarily in the same order), method name, number of type parameters and number of parameters.
  • 対応するパラメーターの宣言では、(が必ずしも同じ順序で)、同じ修飾子を設定する必要がありますと同じ型 (型パラメーター名の相違) を除く。Corresponding parameters in the declarations must have the same modifiers (although not necessarily in the same order) and the same types (modulo differences in type parameter names).
  • 宣言内の対応する型パラメーター (型パラメーター名の相違) を除くと同じ制約があります。Corresponding type parameters in the declarations must have the same constraints (modulo differences in type parameter names).

部分メソッドの実装宣言は、対応する部分メソッドの定義宣言と同じ部分に表示できます。An implementing partial method declaration can appear in the same part as the corresponding defining partial method declaration.

部分メソッドが定義するだけでは、オーバー ロードの解決に関与します。Only a defining partial method participates in overload resolution. したがって、実装宣言が指定されているかどうかを示す invocation 式は、部分メソッドの呼び出しを解決します。Thus, whether or not an implementing declaration is given, invocation expressions may resolve to invocations of the partial method. 部分メソッドは常に返すためvoid、このような呼び出しの式の式ステートメントは常になります。Because a partial method always returns void, such invocation expressions will always be expression statements. さらに、部分メソッドは暗黙的にあるためprivate、このようなステートメントは常に内で部分メソッドを宣言する型宣言の部分の 1 つ発生します。Furthermore, because a partial method is implicitly private, such statements will always occur within one of the parts of the type declaration within which the partial method is declared.

部分型の宣言の一部に特定の部分メソッドの実装宣言が含まれていない場合、それを呼び出す任意の式ステートメントは結合型の宣言から削除だけです。If no part of a partial type declaration contains an implementing declaration for a given partial method, any expression statement invoking it is simply removed from the combined type declaration. したがって、呼び出しなど、式の構成の式には、実行時に影響はありません。Thus the invocation expression, including any constituent expressions, has no effect at run-time. 部分メソッド自体も削除され、結合型の宣言のメンバーはできません。The partial method itself is also removed and will not be a member of the combined type declaration.

特定の部分メソッドの実装宣言がある場合は、部分メソッドの呼び出しが保持されます。If an implementing declaration exist for a given partial method, the invocations of the partial methods are retained. 部分メソッドでは、次を除く部分メソッドの実装宣言のようなメソッドの宣言に上昇。The partial method gives rise to a method declaration similar to the implementing partial method declaration except for the following:

  • partial修飾子が含まれていません。The partial modifier is not included
  • 結果として得られるメソッドの宣言内の属性は、不特定の順序で、定義と実装の部分メソッド宣言の結合の属性です。The attributes in the resulting method declaration are the combined attributes of the defining and the implementing partial method declaration in unspecified order. 重複は削除されません。Duplicates are not removed.
  • 結果として得られるメソッドの宣言のパラメーターの属性は、不特定の順序で、定義と実装の部分メソッド宣言の対応するパラメーターの結合の属性です。The attributes on the parameters of the resulting method declaration are the combined attributes of the corresponding parameters of the defining and the implementing partial method declaration in unspecified order. 重複は削除されません。Duplicates are not removed.

部分メソッド M の実装宣言がなく、定義宣言を指定した場合、次の制限が適用されます。If a defining declaration but not an implementing declaration is given for a partial method M, the following restrictions apply:

部分メソッドは、ツールによって生成されるものなど、別の部分の動作をカスタマイズする型宣言の 1 つの部分を許可する場合に便利です。Partial methods are useful for allowing one part of a type declaration to customize the behavior of another part, e.g., one that is generated by a tool. 次の部分クラス宣言を検討してください。Consider the following partial class declaration:

partial class Customer
{
    string name;

    public string Name {
        get { return name; }
        set {
            OnNameChanging(value);
            name = value;
            OnNameChanged();
        }

    }

    partial void OnNameChanging(string newName);

    partial void OnNameChanged();
}

他の部分でもないこのクラスがコンパイルされると、部分メソッドの定義宣言とその呼び出しは削除され、結果の結合されたクラス宣言は、次と同等になります。If this class is compiled without any other parts, the defining partial method declarations and their invocations will be removed, and the resulting combined class declaration will be equivalent to the following:

class Customer
{
    string name;

    public string Name {
        get { return name; }
        set { name = value; }
    }
}

別の部分が与えられている、ただし、部分メソッドの実装宣言を提供するものとします。Assume that another part is given, however, which provides implementing declarations of the partial methods:

partial class Customer
{
    partial void OnNameChanging(string newName)
    {
        Console.WriteLine("Changing " + name + " to " + newName);
    }

    partial void OnNameChanged()
    {
        Console.WriteLine("Changed to " + name);
    }
}

結果の結合されたクラス宣言は次と同等になります。Then the resulting combined class declaration will be equivalent to the following:

class Customer
{
    string name;

    public string Name {
        get { return name; }
        set {
            OnNameChanging(value);
            name = value;
            OnNameChanged();
        }

    }

    void OnNameChanging(string newName)
    {
        Console.WriteLine("Changing " + name + " to " + newName);
    }

    void OnNameChanged()
    {
        Console.WriteLine("Changed to " + name);
    }
}

名前のバインドName binding

拡張可能な型の各部分は、同じ名前空間内で宣言する必要があります、パーツは通常、別の名前空間宣言内で書き込まれます。Although each part of an extensible type must be declared within the same namespace, the parts are typically written within different namespace declarations. したがって、異なるusingディレクティブ (ディレクティブを使用して) の各部分に存在する場合があります。Thus, different using directives (Using directives) may be present for each part. 単純な名前を解釈するときに (型推論) のみ 1 つのパーツ内で、usingその一部を囲む名前空間宣言のディレクティブと見なされます。When interpreting simple names (Type inference) within one part, only the using directives of the namespace declaration(s) enclosing that part are considered. これにより、さまざまな部分で異なる意味を持つ同じ識別子可能性があります。This may result in the same identifier having different meanings in different parts:

namespace N
{
    using List = System.Collections.ArrayList;

    partial class A
    {
        List x;                // x has type System.Collections.ArrayList
    }
}

namespace N
{
    using List = Widgets.LinkedList;

    partial class A
    {
        List y;                // y has type Widgets.LinkedList
    }
}

クラス メンバーClass members

クラスのメンバーで導入されたメンバーで構成されているそのclass_member_declarations およびメンバーは、直接基底クラスから継承します。The members of a class consist of the members introduced by its class_member_declarations and the members inherited from the direct base class.

class_member_declaration
    : constant_declaration
    | field_declaration
    | method_declaration
    | property_declaration
    | event_declaration
    | indexer_declaration
    | operator_declaration
    | constructor_declaration
    | destructor_declaration
    | static_constructor_declaration
    | type_declaration
    ;

クラス型のメンバーは、次のカテゴリに分類されます。The members of a class type are divided into the following categories:

  • クラスに関連付けられている定数の値を表す定数 (定数)。Constants, which represent constant values associated with the class (Constants).
  • クラスの変数であるフィールド (フィールド)。Fields, which are the variables of the class (Fields).
  • メソッドで、計算とクラスによって実行できるアクションの実装 (メソッド)。Methods, which implement the computations and actions that can be performed by the class (Methods).
  • プロパティを定義する特性をという名前と読み取りと書き込みのような特性に関連付けられているアクション (プロパティ)。Properties, which define named characteristics and the actions associated with reading and writing those characteristics (Properties).
  • クラスによって生成される通知を定義するには、イベント (イベント)。Events, which define notifications that can be generated by the class (Events).
  • 同じ方法でインデックスを作成するクラスのインスタンスが許可されるインデクサーは、配列として (構文) (インデクサー)。Indexers, which permit instances of the class to be indexed in the same way (syntactically) as arrays (Indexers).
  • クラスのインスタンスに適用できる式の演算子の定義の演算子 (演算子)。Operators, which define the expression operators that can be applied to instances of the class (Operators).
  • インスタンス クラスのインスタンスを初期化するために必要なアクションを実装するコンス トラクター (インスタンス コンス トラクター)Instance constructors, which implement the actions required to initialize instances of the class (Instance constructors)
  • デストラクターで、クラスのインスタンスが完全に破棄される前に実行されるアクションを実装 (デストラクター)。Destructors, which implement the actions to be performed before instances of the class are permanently discarded (Destructors).
  • クラス自体を初期化するために必要なアクションを実装する静的コンス トラクター (静的コンス トラクター)。Static constructors, which implement the actions required to initialize the class itself (Static constructors).
  • 種類は、クラスに対してローカルな型を表す (入れ子になった型)。Types, which represent the types that are local to the class (Nested types).

実行可能コードを含むことのできるメンバーと総称されます、関数メンバーのクラス型。Members that can contain executable code are collectively known as the function members of the class type. クラス型の関数メンバーは、メソッド、プロパティ、イベント、インデクサー、演算子、インスタンス コンス トラクター、デストラクター、およびそのクラス型の静的コンス トラクターです。The function members of a class type are the methods, properties, events, indexers, operators, instance constructors, destructors, and static constructors of that class type.

A class_declaration新しい宣言領域を作成します (宣言)、およびclass_member_declarationですぐに格納されている、クラス_declarationこの宣言領域に新しいメンバーを導入します。A class_declaration creates a new declaration space (Declarations), and the class_member_declarations immediately contained by the class_declaration introduce new members into this declaration space. 次の規則に適用されますclass_member_declaration: %sThe following rules apply to class_member_declarations:

  • インスタンス コンス トラクター、デストラクター、および静的コンス トラクターは、すぐ外側のクラスと同じ名前が必要です。Instance constructors, destructors and static constructors must have the same name as the immediately enclosing class. その他のすべてのメンバーのすぐ外側のクラスの名前とは異なる名前が必要です。All other members must have names that differ from the name of the immediately enclosing class.
  • 定数、フィールド、プロパティ、イベント、または型の名前は、同じクラスで宣言されているその他のすべてのメンバーの名前とは異なる必要があります。The name of a constant, field, property, event, or type must differ from the names of all other members declared in the same class.
  • メソッドの名前は、他のすべての非-のメソッドの名前、同じクラスで宣言されているとは異なる必要があります。The name of a method must differ from the names of all other non-methods declared in the same class. さらに、署名 (シグネチャとオーバー ロード) のメソッドと同じクラスで宣言されている他のすべてのメソッドのシグネチャは異なるし、同じクラスで宣言されている 2 つの方法でのみ異なるシグネチャがない可能性がありますによってrefoutします。In addition, the signature (Signatures and overloading) of a method must differ from the signatures of all other methods declared in the same class, and two methods declared in the same class may not have signatures that differ solely by ref and out.
  • インスタンス コンス トラクターのシグネチャは、同じクラスで宣言されている他のすべてのインスタンス コンス トラクターのシグネチャと異なる必要があり、同じクラスで宣言されている 2 つのコンス トラクターでのみが異なるシグネチャがない可能性がありますrefoutします。The signature of an instance constructor must differ from the signatures of all other instance constructors declared in the same class, and two constructors declared in the same class may not have signatures that differ solely by ref and out.
  • インデクサーのシグネチャは、同じクラスで宣言されている他のすべてのインデクサーの署名とは異なる必要があります。The signature of an indexer must differ from the signatures of all other indexers declared in the same class.
  • 演算子のシグネチャは、同じクラスで宣言されているその他のすべての演算子のシグネチャとは異なる必要があります。The signature of an operator must differ from the signatures of all other operators declared in the same class.

クラス型の継承されたメンバー (継承) クラスの宣言領域の一部ではないです。The inherited members of a class type (Inheritance) are not part of the declaration space of a class. したがって、派生クラスは (これは有効で、継承されたメンバーを非表示になります)、継承されたメンバーと同じ名前またはシグネチャを持つメンバーを宣言できます。Thus, a derived class is allowed to declare a member with the same name or signature as an inherited member (which in effect hides the inherited member).

インスタンスの型The instance type

各クラスの宣言が関連付けられたバインドされた型 (バインドされ、型がバインドされていない)、インスタンス タイプにします。Each class declaration has an associated bound type (Bound and unbound types), the instance type. 構築された型を作成して、ジェネリック クラス宣言のインスタンスの型の形式が (構築型)、型宣言からで指定された型の各引数が、対応する入力パラメーター。For a generic class declaration, the instance type is formed by creating a constructed type (Constructed types) from the type declaration, with each of the supplied type arguments being the corresponding type parameter. インスタンスの型は、型パラメーターを使用するためにのみ使用できます、型パラメーターがスコープにあります。つまり、クラス宣言内で。Since the instance type uses the type parameters, it can only be used where the type parameters are in scope; that is, inside the class declaration. インスタンスの型の型は、thisクラス宣言内で記述されたコード。The instance type is the type of this for code written inside the class declaration. 非ジェネリック クラス、インスタンスの型は、宣言されたクラスだけです。For non-generic classes, the instance type is simply the declared class. インスタンスの型といくつかのクラス宣言を次に示します。The following shows several class declarations along with their instance types:

class A<T>                           // instance type: A<T>
{
    class B {}                       // instance type: A<T>.B
    class C<U> {}                    // instance type: A<T>.C<U>
}

class D {}                           // instance type: D

構築された型のメンバーMembers of constructed types

構築された型の非継承メンバーが、それぞれに置き換えることによって取得したtype_parameter 、対応するメンバーの宣言でtype_argument構築された型のです。The non-inherited members of a constructed type are obtained by substituting, for each type_parameter in the member declaration, the corresponding type_argument of the constructed type. 切り替え処理は、型の宣言の意味に基づいており、単なるテキストの置換ではありません。The substitution process is based on the semantic meaning of type declarations, and is not simply textual substitution.

たとえば、ジェネリック クラス宣言について考えます。For example, given the generic class declaration

class Gen<T,U>
{
    public T[,] a;
    public void G(int i, T t, Gen<U,T> gt) {...}
    public U Prop { get {...} set {...} }
    public int H(double d) {...}
}

構築された型Gen<int[],IComparable<string>>に次のメンバーがあります。the constructed type Gen<int[],IComparable<string>> has the following members:

public int[,][] a;
public void G(int i, int[] t, Gen<IComparable<string>,int[]> gt) {...}
public IComparable<string> Prop { get {...} set {...} }
public int H(double d) {...}

メンバーの型aジェネリック クラス宣言でGenは"の 2 次元配列T"ため、メンバーの型a"の1次元配列の2次元配列をは、上記の構築された型int"、またはint[,][]します。The type of the member a in the generic class declaration Gen is "two-dimensional array of T", so the type of the member a in the constructed type above is "two-dimensional array of one-dimensional array of int", or int[,][].

インスタンス関数メンバーの種類内thisインスタンスの型は、(インスタンス型) 含む宣言のです。Within instance function members, the type of this is the instance type (The instance type) of the containing declaration.

ジェネリック クラスのすべてのメンバーは、直接、または構築された型の一部として、外側のクラスからの型パラメーターを使用できます。All members of a generic class can use type parameters from any enclosing class, either directly or as part of a constructed type. 構築された型の特定が閉じられたときに (オープンとクローズ型) が使用される実行時には、型パラメーターの使用は、構築された型に指定された実際の型引数に置き換えられます。When a particular closed constructed type (Open and closed types) is used at run-time, each use of a type parameter is replaced with the actual type argument supplied to the constructed type. 例:For example:

class C<V>
{
    public V f1;
    public C<V> f2 = null;

    public C(V x) {
        this.f1 = x;
        this.f2 = this;
    }
}

class Application
{
    static void Main() {
        C<int> x1 = new C<int>(1);
        Console.WriteLine(x1.f1);        // Prints 1

        C<double> x2 = new C<double>(3.1415);
        Console.WriteLine(x2.f1);        // Prints 3.1415
    }
}

継承Inheritance

クラス継承直接基底クラス型のメンバー。A class inherits the members of its direct base class type. 継承では、クラスが暗黙的にインスタンス コンス トラクター、デストラクター、および基底クラスの静的コンス トラクターを除く、直接基底クラス型のすべてのメンバーを格納することを意味します。Inheritance means that a class implicitly contains all members of its direct base class type, except for the instance constructors, destructors and static constructors of the base class. 継承する場合は、いくつかの重要な側面は次のとおりです。Some important aspects of inheritance are:

  • 継承は推移的です。Inheritance is transitive. 場合Cから派生B、およびBから派生A、しCで宣言されたメンバーを継承Bで宣言されたメンバーとAします。If C is derived from B, and B is derived from A, then C inherits the members declared in B as well as the members declared in A.
  • 派生クラスでは、その直接の基本クラスを拡張します。A derived class extends its direct base class. 派生クラスは、継承するメンバーに新しいメンバーを追加できますが、継承されたメンバーの定義を削除することはできません。A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member.
  • インスタンス コンス トラクター、デストラクター、および静的コンス トラクターは継承されませんが、宣言されたアクセシビリティに関係なく、他のすべてのメンバーは、(メンバー アクセス)。Instance constructors, destructors, and static constructors are not inherited, but all other members are, regardless of their declared accessibility (Member access). ただし、によって宣言されたアクセシビリティ、継承されたメンバーができない派生クラスでアクセスできます。However, depending on their declared accessibility, inherited members might not be accessible in a derived class.
  • 派生クラスはを非表示に(継承によって非表示) 同じ名前またはシグネチャを持つ新しいメンバーを宣言することで、継承されたメンバー。A derived class can hide (Hiding through inheritance) inherited members by declaring new members with the same name or signature. そのメンバーは削除継承されたメンバーが隠ぺいされてただしは、単に、そのメンバーは派生クラスから直接アクセスできません。Note however that hiding an inherited member does not remove that member—it merely makes that member inaccessible directly through the derived class.
  • クラスのインスタンスには、一連クラスとその基本クラスでは、暗黙的な変換で宣言されているすべてのインスタンス フィールドにはが含まれています (暗黙の参照変換) クラスの派生型からその基底クラス型のいずれかに存在します。An instance of a class contains a set of all instance fields declared in the class and its base classes, and an implicit conversion (Implicit reference conversions) exists from a derived class type to any of its base class types. したがって、いくつかの派生クラスのインスタンスへの参照は、その基本クラスのいずれかのインスタンスへの参照として処理できます。Thus, a reference to an instance of some derived class can be treated as a reference to an instance of any of its base classes.
  • クラスは、仮想メソッド、プロパティ、およびインデクサーを宣言し、派生クラスは、これらの関数メンバーの実装をオーバーライドできます。A class can declare virtual methods, properties, and indexers, and derived classes can override the implementation of these function members. これにより、クラス メンバー関数の呼び出しによって実行されたアクションは、その関数のメンバーが呼び出されるインスタンスの実行時の型によって異なります、ポリモーフィックな動作が発生することができます。This enables classes to exhibit polymorphic behavior wherein the actions performed by a function member invocation varies depending on the run-time type of the instance through which that function member is invoked.

構築済みクラス型の継承されたメンバーは、直接の基本クラス型のメンバー (基底クラス)、対応する型の各インスタンスに対して構築された型の型引数を代入することによってこれが見つかった内のパラメーター、 class_base仕様。The inherited member of a constructed class type are the members of the immediate base class type (Base classes), which is found by substituting the type arguments of the constructed type for each occurrence of the corresponding type parameters in the class_base specification. さらに、これらのメンバーがそれぞれの置換によって変換されますtype_parameter 、対応するメンバーの宣言でtype_argumentclass_base指定。These members, in turn, are transformed by substituting, for each type_parameter in the member declaration, the corresponding type_argument of the class_base specification.

class B<U>
{
    public U F(long index) {...}
}

class D<T>: B<T[]>
{
    public T G(string s) {...}
}

上記の例では、構築された型でD<int>非継承メンバーを持つpublic int G(string s)型引数を代入することによって取得int、型パラメーターに対してTIn the above example, the constructed type D<int> has a non-inherited member public int G(string s) obtained by substituting the type argument int for the type parameter T. D<int> クラス宣言から継承されたメンバーがありますBします。D<int> also has an inherited member from the class declaration B. この継承されたメンバーを最初に基本クラスの型を決定することで決定B<int[]>D<int>に置き換えることによってintT基底クラスの指定でB<T[]>します。This inherited member is determined by first determining the base class type B<int[]> of D<int> by substituting int for T in the base class specification B<T[]>. 次に、型引数として、 Bint[]を置き換えるUpublic U F(long index)、継承されたメンバーを生成public int[] F(long index)します。Then, as a type argument to B, int[] is substituted for U in public U F(long index), yielding the inherited member public int[] F(long index).

New 修飾子The new modifier

A class_member_declaration継承されたメンバーと同じ名前またはシグネチャを持つメンバーを宣言できます。A class_member_declaration is permitted to declare a member with the same name or signature as an inherited member. この場合、派生クラスのメンバーといいますを非表示に基底クラスのメンバー。When this occurs, the derived class member is said to hide the base class member. 継承されたメンバーを非表示で、エラーはありませんが、コンパイラ警告を発し。Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. 警告を抑制するには、派生クラスのメンバーの宣言を含めることができます、new修飾子を派生メンバーでは、基本メンバーを非表示にするものであるかを示します。To suppress the warning, the declaration of the derived class member can include a new modifier to indicate that the derived member is intended to hide the base member. このトピックの説明でさらに継承による隠ぺいします。This topic is discussed further in Hiding through inheritance.

場合、new継承されたメンバーを隠ぺいしない宣言に修飾子を含めると、それに対応する警告が表示されます。If a new modifier is included in a declaration that doesn't hide an inherited member, a warning to that effect is issued. 削除することによってこの警告が抑制され、new修飾子。This warning is suppressed by removing the new modifier.

アクセス修飾子Access modifiers

A class_member_declaration宣言されたアクセシビリティの 5 つの可能な種類のいずれかを持つことができます (宣言されたアクセシビリティ): publicprotected internalprotectedinternal、またはprivateします。A class_member_declaration can have any one of the five possible kinds of declared accessibility (Declared accessibility): public, protected internal, protected, internal, or private. を除き、protected internalを 1 つ以上のアクセス修飾子を指定すると、コンパイル エラーは、の組み合わせ。Except for the protected internal combination, it is a compile-time error to specify more than one access modifier. ときに、 class_member_declaration 、アクセス修飾子を含まないprivateと見なされます。When a class_member_declaration does not include any access modifiers, private is assumed.

構成要素型Constituent types

メンバーの宣言で使用される型は、そのメンバーの構成要素の型と呼ばれます。Types that are used in the declaration of a member are called the constituent types of that member. 使用可能な構成要素である型は、定数、フィールド、プロパティ、イベント、またはインデクサーの型、演算子、またはメソッドの戻り値の型およびメソッド、インデクサー、演算子、またはインスタンスのコンス トラクターのパラメーターの型。Possible constituent types are the type of a constant, field, property, event, or indexer, the return type of a method or operator, and the parameter types of a method, indexer, operator, or instance constructor. メンバーの構成要素の型は、少なくともそのメンバー自体と同程度にアクセスである必要があります (アクセシビリティ制約)。The constituent types of a member must be at least as accessible as that member itself (Accessibility constraints).

静的メンバーとインスタンス メンバーStatic and instance members

クラスのメンバーは、いずれかの静的メンバーまたはインスタンス メンバーします。Members of a class are either static members or instance members. 一般に、静的メンバーとしてクラス型とオブジェクト (クラス型のインスタンス) に属するものとしてインスタンス メンバーに属していると考えると便利です。Generally speaking, it is useful to think of static members as belonging to class types and instance members as belonging to objects (instances of class types).

フィールド、メソッド、プロパティ、イベント、演算子、またはコンス トラクターの宣言が含まれています、static修飾子は、静的メンバーを宣言します。When a field, method, property, event, operator, or constructor declaration includes a static modifier, it declares a static member. さらに、定数または型の宣言には、静的メンバーを暗黙的に宣言します。In addition, a constant or type declaration implicitly declares a static member. 静的メンバーには、次の特性があります。Static members have the following characteristics:

  • 静的メンバーMで言及されている、 member_access (メンバー アクセス) フォームのE.ME含まれる型を表す必要がありますMします。When a static member M is referenced in a member_access (Member access) of the form E.M, E must denote a type containing M. コンパイル時エラーにはEインスタンスを表すとします。It is a compile-time error for E to denote an instance.
  • 静的フィールドは、閉じられた特定のクラス型のすべてのインスタンスで共有する 1 つだけの記憶域の場所を識別します。A static field identifies exactly one storage location to be shared by all instances of a given closed class type. 閉じられた特定のクラス型のインスタンスの数が作成されては、静的フィールドの 1 つだけコピーします。No matter how many instances of a given closed class type are created, there is only ever one copy of a static field.
  • 静的な関数メンバー (メソッド、プロパティ、イベント、演算子、またはコンス トラクター) が特定のインスタンスで動作しないを参照すると、コンパイル時エラーthisでこのような関数メンバー。A static function member (method, property, event, operator, or constructor) does not operate on a specific instance, and it is a compile-time error to refer to this in such a function member.

フィールド、メソッド、プロパティ、イベント、インデクサー、コンス トラクターまたはデストラクターの宣言が含まれていない場合、static修飾子は、インスタンス メンバーを宣言します。When a field, method, property, event, indexer, constructor, or destructor declaration does not include a static modifier, it declares an instance member. (インスタンス メンバーと呼ぶことが、非静的メンバーです。)インスタンス メンバーには、次の特性があります。(An instance member is sometimes called a non-static member.) Instance members have the following characteristics:

  • インスタンス メンバーとMで言及されている、 member_access (メンバー アクセス) フォームのE.ME を含む型のインスタンスを表す必要がありますM.When an instance member M is referenced in a member_access (Member access) of the form E.M, E must denote an instance of a type containing M. バインディング時のエラーにはE型を表すとします。It is a binding-time error for E to denote a type.
  • クラスのすべてのインスタンスには、別のクラスのすべてのインスタンス フィールドのセットが含まれています。Every instance of a class contains a separate set of all instance fields of the class.
  • インスタンス関数メンバー (メソッド、プロパティ、インデクサー、インスタンス コンス トラクターまたはデストラクター) は、クラスの特定のインスタンスを操作し、としてこのインスタンスにアクセスできるthis(このアクセス)。An instance function member (method, property, indexer, instance constructor, or destructor) operates on a given instance of the class, and this instance can be accessed as this (This access).

次の例は、静的にアクセスするためのルールとインスタンス メンバーを示しています。The following example illustrates the rules for accessing static and instance members:

class Test
{
    int x;
    static int y;

    void F() {
        x = 1;            // Ok, same as this.x = 1
        y = 1;            // Ok, same as Test.y = 1
    }

    static void G() {
        x = 1;            // Error, cannot access this.x
        y = 1;            // Ok, same as Test.y = 1
    }

    static void Main() {
        Test t = new Test();
        t.x = 1;          // Ok
        t.y = 1;          // Error, cannot access static member through instance
        Test.x = 1;       // Error, cannot access instance member through type
        Test.y = 1;       // Ok
    }
}

Fメソッドは、インスタンス関数メンバーの表示をsimple_name (簡易名) インスタンスのメンバーと静的メンバーの両方にアクセスするために使用できます。The F method shows that in an instance function member, a simple_name (Simple names) can be used to access both instance members and static members. Gメソッドは、静的な関数メンバーであるを通じてインスタンス メンバーにアクセスすると、コンパイル時エラーを表示、 simple_nameします。The G method shows that in a static function member, it is a compile-time error to access an instance member through a simple_name. Mainメソッドを示していますが、 member_access (メンバー アクセス) インスタンス、インスタンス メンバーにアクセスする必要があります、静的メンバーは、型を使ってアクセスする必要があります。The Main method shows that in a member_access (Member access), instance members must be accessed through instances, and static members must be accessed through types.

入れ子にされた型Nested types

クラスまたは構造体宣言内で宣言された型が呼び出される、入れ子にされた型します。A type declared within a class or struct declaration is called a nested type. コンパイル単位または名前空間内で宣言された型が呼び出される、に入れ子にされた型します。A type that is declared within a compilation unit or namespace is called a non-nested type.

In the example

using System;

class A
{
    class B
    {
        static void F() {
            Console.WriteLine("A.B.F");
        }
    }
}

クラスBクラス内で宣言されているため、入れ子にされた型は、 A、およびクラスAに入れ子にされた型は、コンパイル単位内で宣言されているためです。class B is a nested type because it is declared within class A, and class A is a non-nested type because it is declared within a compilation unit.

完全修飾名Fully qualified name

完全修飾名 (完全修飾名) 入れ子にされた型はS.N場所Sでどの種類の型の完全修飾名は、Nは宣言されています。The fully qualified name (Fully qualified names) for a nested type is S.N where S is the fully qualified name of the type in which type N is declared.

アクセシビリティの宣言Declared accessibility

非入れ子にされた型を持つことができますpublicまたはinternalアクセシビリティで宣言されていて、internal既定でアクセシビリティを宣言します。Non-nested types can have public or internal declared accessibility and have internal declared accessibility by default. 入れ子にされた型はさらにそれを含む型は、クラスまたは構造体かどうかに応じて、宣言されたアクセシビリティの 1 つまたは複数の形式を別途、これらの種類の宣言されたアクセシビリティを持つことができます。Nested types can have these forms of declared accessibility too, plus one or more additional forms of declared accessibility, depending on whether the containing type is a class or struct:

  • クラスで宣言されている入れ子にされた型が宣言されたアクセシビリティの 5 つの形式のいずれかを持つことができます (publicprotected internalprotectedinternal、またはprivate) と、他のクラス メンバーのように既定値はprivate宣言アクセシビリティ。A nested type that is declared in a class can have any of five forms of declared accessibility (public, protected internal, protected, internal, or private) and, like other class members, defaults to private declared accessibility.
  • 構造体で宣言されている入れ子にされた型が宣言されたアクセシビリティの 3 つの形式のいずれかを持つことができます (publicinternal、またはprivate) と、他の構造体のメンバーのように既定値はprivateアクセシビリティを宣言します。A nested type that is declared in a struct can have any of three forms of declared accessibility (public, internal, or private) and, like other struct members, defaults to private declared accessibility.

例では、The example

public class List
{
    // Private data structure
    private class Node
    { 
        public object Data;
        public Node Next;

        public Node(object data, Node next) {
            this.Data = data;
            this.Next = next;
        }
    }

    private Node first = null;
    private Node last = null;

    // Public interface
    public void AddToFront(object o) {...}
    public void AddToBack(object o) {...}
    public object RemoveFromFront() {...}
    public object RemoveFromBack() {...}
    public int Count { get {...} }
}

プライベートの入れ子になったクラスを宣言してNodeします。declares a private nested class Node.

非表示Hiding

入れ子にされた型の非表示にすることがあります (名前の隠ぺい) ベースのメンバー。A nested type may hide (Name hiding) a base member. new修飾子が入れ子にされた型の宣言で許可されるため、非表示を明示的に表すことができます。The new modifier is permitted on nested type declarations so that hiding can be expressed explicitly. 例では、The example

using System;

class Base
{
    public static void M() {
        Console.WriteLine("Base.M");
    }
}

class Derived: Base 
{
    new public class M 
    {
        public static void F() {
            Console.WriteLine("Derived.M.F");
        }
    }
}

class Test 
{
    static void Main() {
        Derived.M.F();
    }
}

入れ子になったクラスを示しています。Mメソッドを非表示にMで定義されているBaseします。shows a nested class M that hides the method M defined in Base.

このアクセスthis access

入れ子にされた型とそれを含む型にに関して特別なリレーションシップがありませんthis_access (このアクセス)。A nested type and its containing type do not have a special relationship with regard to this_access (This access). 具体的には、this内での入れ子にされた型には使用できません、包含する型のインスタンス メンバーを参照してください。Specifically, this within a nested type cannot be used to refer to instance members of the containing type. 入れ子にされた型がそれを含む型のインスタンス メンバーへのアクセスを必要がある場合、アクセスを提供することで提供できます、thisの入れ子にされた型のコンス トラクター引数として含んでいる型のインスタンス。In cases where a nested type needs access to the instance members of its containing type, access can be provided by providing the this for the instance of the containing type as a constructor argument for the nested type. 次の例The following example

using System;

class C
{
    int i = 123;

    public void F() {
        Nested n = new Nested(this);
        n.G();
    }

    public class Nested
    {
        C this_c;

        public Nested(C c) {
            this_c = c;
        }

        public void G() {
            Console.WriteLine(this_c.i);
        }
    }
}

class Test
{
    static void Main() {
        C c = new C();
        c.F();
    }
}

この方法を示しています。shows this technique. インスタンスCのインスタンスを作成しますNested独自渡しますthisNestedのコンス トラクターへの後続のアクセスを提供するためにCのインスタンス メンバーです。An instance of C creates an instance of Nested and passes its own this to Nested's constructor in order to provide subsequent access to C's instance members.

含んでいる型のプライベート、プロテクト メンバーへのアクセスAccess to private and protected members of the containing type

入れ子にされた型を持つ、包含する型のメンバーを含む、包含する型にアクセスできるメンバーのすべてにアクセスするがprivateprotectedアクセシビリティを宣言します。A nested type has access to all of the members that are accessible to its containing type, including members of the containing type that have private and protected declared accessibility. 例では、The example

using System;

class C 
{
    private static void F() {
        Console.WriteLine("C.F");
    }

    public class Nested 
    {
        public static void G() {
            F();
        }
    }
}

class Test 
{
    static void Main() {
        C.Nested.G();
    }
}

クラスを示していますC入れ子になったクラスを格納しているNestedします。shows a class C that contains a nested class Nested. 内でNested、メソッドG静的メソッドを呼び出してFで定義されているC、およびF宣言されたアクセシビリティをプライベートにします。Within Nested, the method G calls the static method F defined in C, and F has private declared accessibility.

入れ子にされた型は、それを含む型の基本型で定義されている保護されたメンバーもアクセスできます。A nested type also may access protected members defined in a base type of its containing type. In the example

using System;

class Base 
{
    protected void F() {
        Console.WriteLine("Base.F");
    }
}

class Derived: Base 
{
    public class Nested 
    {
        public void G() {
            Derived d = new Derived();
            d.F();        // ok
        }
    }
}

class Test 
{
    static void Main() {
        Derived.Nested n = new Derived.Nested();
        n.G();
    }
}

入れ子になったクラスDerived.Nestedプロテクト メソッドにアクセスするFで定義されているDerivedの基本クラス、Baseによりのインスタンスを介して呼び出すDerivedします。the nested class Derived.Nested accesses the protected method F defined in Derived's base class, Base, by calling through an instance of Derived.

ジェネリック クラスの入れ子にされた型Nested types in generic classes

ジェネリック クラス宣言は、入れ子になった型宣言を含めることができます。A generic class declaration can contain nested type declarations. 外側のクラスの型パラメーターは、入れ子にされた型で使用できます。The type parameters of the enclosing class can be used within the nested types. 入れ子になった型宣言は、入れ子にされた型にのみ適用される追加の型パラメーターを含めることができます。A nested type declaration can contain additional type parameters that apply only to the nested type.

ジェネリック クラス宣言内に含まれるすべての型宣言は、暗黙的にジェネリック型の宣言です。Every type declaration contained within a generic class declaration is implicitly a generic type declaration. ジェネリック型の中で入れ子になった型への参照を書き込むときに、型引数を含む、コンテナーの構築された型が指定する必要があります。When writing a reference to a type nested within a generic type, the containing constructed type, including its type arguments, must be named. ただしから外側のクラス内で入れ子にされた型は修飾しないで使用できる;外側のクラスのインスタンスの型は、入れ子にされた型を構築するときに暗黙的に使用できます。However, from within the outer class, the nested type can be used without qualification; the instance type of the outer class can be implicitly used when constructing the nested type. 次の例は、作成から構築された型を参照する 3 つの正しい方法を示しています。 Inner; 最初の 2 つは等価です。The following example shows three different correct ways to refer to a constructed type created from Inner; the first two are equivalent:

class Outer<T>
{
    class Inner<U>
    {
        public static void F(T t, U u) {...}
    }

    static void F(T t) {
        Outer<T>.Inner<string>.F(t, "abc");      // These two statements have
        Inner<string>.F(t, "abc");               // the same effect

        Outer<int>.Inner<string>.F(3, "abc");    // This type is different

        Outer.Inner<string>.F(t, "abc");         // Error, Outer needs type arg
    }
}

不適切なプログラミング スタイルでは、入れ子にされた型の型パラメーター メンバーを非表示にしたり、外側の型で宣言されたパラメーターを入力します。Although it is bad programming style, a type parameter in a nested type can hide a member or type parameter declared in the outer type:

class Outer<T>
{
    class Inner<T>        // Valid, hides Outer's T
    {
        public T t;       // Refers to Inner's T
    }
}

予約済みのメンバー名Reserved member names

C# 実行時の基本的な実装をプロパティ、イベント、またはインデクサーでは、各ソース メンバー宣言を容易に実装は、メンバーの宣言、名前、およびその型の種類に基づく 2 つのメソッド シグネチャを予約する必要があります。To facilitate the underlying C# run-time implementation, for each source member declaration that is a property, event, or indexer, the implementation must reserve two method signatures based on the kind of the member declaration, its name, and its type. 基になるランタイムの実装を行わない場合でも、これらのいずれかに一致するシグネチャを持つメンバーには、署名が予約されています。 を宣言するプログラムのコンパイル時エラーがこれらの予約を使用します。It is a compile-time error for a program to declare a member whose signature matches one of these reserved signatures, even if the underlying run-time implementation does not make use of these reservations.

予約済みの名前は宣言されていない、したがって、メンバーの参照に参加していません。The reserved names do not introduce declarations, thus they do not participate in member lookup. ただし、宣言のシグネチャが継承に参加して予約済みのメソッドの関連 (継承) と非表示にできると、new修飾子 (new 修飾子)。However, a declaration's associated reserved method signatures do participate in inheritance (Inheritance), and can be hidden with the new modifier (The new modifier).

これらの名前の予約には、次の 3 つの目的があります。The reservation of these names serves three purposes:

  • Get のメソッド名として通常の識別子を使用するか、c# 言語機能にアクセスを設定するには、基になる実装をできるようにします。To allow the underlying implementation to use an ordinary identifier as a method name for get or set access to the C# language feature.
  • その他の言語の get メソッド名として通常の識別子を使用して相互運用または c# 言語機能にアクセスを設定できるようにします。To allow other languages to interoperate using an ordinary identifier as a method name for get or set access to the C# language feature.
  • ソースが 1 つの準拠コンパイラによって受け入れられるようにがによって許可される、ことで予約されているメンバーの仕様名一貫性のあるすべての c# 実装でします。To help ensure that the source accepted by one conforming compiler is accepted by another, by making the specifics of reserved member names consistent across all C# implementations.

デストラクターの宣言 (デストラクター) もシグネチャを予約できると、(デストラクター予約されているメンバーの名前)。The declaration of a destructor (Destructors) also causes a signature to be reserved (Member names reserved for destructors).

プロパティ用に予約されているメンバー名Member names reserved for properties

プロパティのP(プロパティ) 型のT、次のシグネチャは予約されています。For a property P (Properties) of type T, the following signatures are reserved:

T get_P();
void set_P(T value);

プロパティが読み取り専用または書き込み専用の場合でも、両方の署名が予約されています。Both signatures are reserved, even if the property is read-only or write-only.

In the example

using System;

class A
{
    public int P {
        get { return 123; }
    }
}

class B: A
{
    new public int get_P() {
        return 456;
    }

    new public void set_P(int value) {
    }
}

class Test
{
    static void Main() {
        B b = new B();
        A a = b;
        Console.WriteLine(a.P);
        Console.WriteLine(b.P);
        Console.WriteLine(b.get_P());
    }
}

クラスA読み取り専用プロパティを定義するP、シグネチャが予約get_Pset_Pメソッド。a class A defines a read-only property P, thus reserving signatures for get_P and set_P methods. クラスBから派生したA両方のこれらの予約済みの署名を非表示にします。A class B derives from A and hides both of these reserved signatures. この例では、出力が生成されます。The example produces the output:

123
123
456

イベント用に予約されているメンバー名Member names reserved for events

イベントのE(イベント) デリゲート型のT、次のシグネチャは予約されています。For an event E (Events) of delegate type T, the following signatures are reserved:

void add_E(T handler);
void remove_E(T handler);

インデクサー用に予約されているメンバー名Member names reserved for indexers

インデクサーの (インデクサー) 型のTパラメーター リストでL、次のシグネチャは予約されています。For an indexer (Indexers) of type T with parameter-list L, the following signatures are reserved:

T get_Item(L);
void set_Item(L, T value);

インデクサーは読み取り専用または書き込み専用で場合でも、両方の署名が予約されています。Both signatures are reserved, even if the indexer is read-only or write-only.

さらに、メンバー名Itemは予約されています。Furthermore the member name Item is reserved.

デストラクターの予約済みのメンバー名Member names reserved for destructors

デストラクターを含むクラスの (デストラクター)、次のシグネチャは予約されています。For a class containing a destructor (Destructors), the following signature is reserved:

void Finalize();

定数Constants

A定数定数値を表すクラスのメンバーである: コンパイル時に計算できる値。A constant is a class member that represents a constant value: a value that can be computed at compile-time. A constant_declaration指定された型の 1 つまたは複数の定数が導入されています。A constant_declaration introduces one or more constants of a given type.

constant_declaration
    : attributes? constant_modifier* 'const' type constant_declarators ';'
    ;

constant_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    ;

constant_declarators
    : constant_declarator (',' constant_declarator)*
    ;

constant_declarator
    : identifier '=' constant_expression
    ;

A constant_declarationのセットを含めることができます属性(属性)、new修飾子 (new 修飾子)、有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)。A constant_declaration may include a set of attributes (Attributes), a new modifier (The new modifier), and a valid combination of the four access modifiers (Access modifiers). 属性と修飾子で宣言されたメンバーのすべてに適用されます、 constant_declarationします。The attributes and modifiers apply to all of the members declared by the constant_declaration. 定数は、静的メンバーと見なされる場合でも、 constant_declarationが必要し、は、どちらも、static修飾子。Even though constants are considered static members, a constant_declaration neither requires nor allows a static modifier. 同じ修飾子を定数宣言内で複数回のエラーになります。It is an error for the same modifier to appear multiple times in a constant declaration.

constant_declaration宣言によって導入されるメンバーの種類を指定します。The type of a constant_declaration specifies the type of the members introduced by the declaration. 型がのリストが続くconstant_declarators、新しいメンバーは、それぞれが導入されています。The type is followed by a list of constant_declarators, each of which introduces a new member. A constant_declaratorから成る、識別子後に、メンバーの名前を示す、"="トークン、その後に、 constant_expression (定数式) のメンバーの値を提供します。A constant_declarator consists of an identifier that names the member, followed by an "=" token, followed by a constant_expression (Constant expressions) that gives the value of the member.

定数で指定された宣言である必要がありますsbytebyteshortushortintuintlongulongcharfloatdoubledecimalboolstringenum_type、またはreference_typeします。The type specified in a constant declaration must be sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum_type, or a reference_type. constant_expression対象の型の場合、または暗黙的な変換によって対象の型に変換できる型の値を生成する必要があります (暗黙的な変換)。Each constant_expression must yield a value of the target type or of a type that can be converted to the target type by an implicit conversion (Implicit conversions).

定数は、少なくとも定数自体と同程度にアクセスする必要があります (アクセシビリティ制約)。The type of a constant must be at least as accessible as the constant itself (Accessibility constraints).

定数の値が使用する式で取得した、 simple_name (簡易名) またはmember_access (メンバー アクセス)。The value of a constant is obtained in an expression using a simple_name (Simple names) or a member_access (Member access).

定数できます自体の一部をconstant_expressionします。A constant can itself participate in a constant_expression. したがってが必要な構成要素で定数を使用すること、 constant_expressionします。Thus, a constant may be used in any construct that requires a constant_expression. このような構造の例として、caseラベル、goto caseステートメント、enumメンバーの宣言、属性、およびその他の定数の宣言。Examples of such constructs include case labels, goto case statements, enum member declarations, attributes, and other constant declarations.

」の説明に従って定数式constant_expressionコンパイル時に完全に評価される式を指定します。As described in Constant expressions, a constant_expression is an expression that can be fully evaluated at compile-time. 以降の null 以外の値を作成する唯一の方法、 reference_type以外stringが適用される、new演算子、しているので、newで演算子は使用できません、 constant_式の定数にのみ指定できる値reference_type以外 sstringnullします。Since the only way to create a non-null value of a reference_type other than string is to apply the new operator, and since the new operator is not permitted in a constant_expression, the only possible value for constants of reference_types other than string is null.

定数値のシンボル名が必要なときにその値の型は、定数宣言で許可されていませんが、またはによってコンパイル時に値を計算できない場合、 constant_expressionreadonly (フィールド読み取り専用フィールド) 代わりに使用される可能性があります。When a symbolic name for a constant value is desired, but when the type of that value is not permitted in a constant declaration, or when the value cannot be computed at compile-time by a constant_expression, a readonly field (Readonly fields) may be used instead.

複数の定数を宣言する定数宣言では、属性、修飾子、および型の単一の定数の複数の宣言と同じです。A constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same attributes, modifiers, and type. 次に例を示します。For example

class A
{
    public const double X = 1.0, Y = 2.0, Z = 3.0;
}

上記の式は、次の式と同じです。is equivalent to

class A
{
    public const double X = 1.0;
    public const double Y = 2.0;
    public const double Z = 3.0;
}

定数は、循環依存関係がない限り、同じプログラム内の他の定数に依存して許可されます。Constants are permitted to depend on other constants within the same program as long as the dependencies are not of a circular nature. コンパイラは、適切な順序で定数の宣言を評価する自動的に配置します。The compiler automatically arranges to evaluate the constant declarations in the appropriate order. In the example

class A
{
    public const int X = B.Z + 1;
    public const int Y = 10;
}

class B
{
    public const int Z = A.Y + 1;
}

コンパイラは最初に評価A.Yを評価し、 B.Z、最後に評価およびA.X、値を生成101112します。the compiler first evaluates A.Y, then evaluates B.Z, and finally evaluates A.X, producing the values 10, 11, and 12. 定数宣言可能性があります、他のプログラムから定数によって異なりますが、このような依存関係は一方向にのみです。Constant declarations may depend on constants from other programs, but such dependencies are only possible in one direction. 場合に、上記の例を参照するAB宣言されている別のプログラムは可能性がありますA.Xに依存するB.ZB.Zに同時にではなく依存でしたしA.Yします。Referring to the example above, if A and B were declared in separate programs, it would be possible for A.X to depend on B.Z, but B.Z could then not simultaneously depend on A.Y.

フィールドFields

Aフィールドオブジェクトまたはクラスに関連付けられている変数を表すメンバーします。A field is a member that represents a variable associated with an object or class. A field_declaration指定された型の 1 つまたは複数のフィールドが導入されています。A field_declaration introduces one or more fields of a given type.

field_declaration
    : attributes? field_modifier* type variable_declarators ';'
    ;

field_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'readonly'
    | 'volatile'
    | field_modifier_unsafe
    ;

variable_declarators
    : variable_declarator (',' variable_declarator)*
    ;

variable_declarator
    : identifier ('=' variable_initializer)?
    ;

variable_initializer
    : expression
    | array_initializer
    ;

A field_declarationのセットを含めることができます属性(属性)、new修飾子 (new 修飾子)、有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)、およびstatic修飾子 (静的およびインスタンス フィールド)。A field_declaration may include a set of attributes (Attributes), a new modifier (The new modifier), a valid combination of the four access modifiers (Access modifiers), and a static modifier (Static and instance fields). さらに、 field_declaration含めることができます、readonly修飾子 (読み取り専用フィールド) またはvolatile修飾子 (Volatile フィールド) 両方ではないです。In addition, a field_declaration may include a readonly modifier (Readonly fields) or a volatile modifier (Volatile fields) but not both. 属性と修飾子で宣言されたメンバーのすべてに適用されます、 field_declarationします。The attributes and modifiers apply to all of the members declared by the field_declaration. 同じ修飾子をフィールド宣言内で複数回のエラーになります。It is an error for the same modifier to appear multiple times in a field declaration.

field_declaration宣言によって導入されるメンバーの種類を指定します。The type of a field_declaration specifies the type of the members introduced by the declaration. 型がのリストが続くvariable_declarators、新しいメンバーは、それぞれが導入されています。The type is followed by a list of variable_declarators, each of which introduces a new member. A variable_declaratorから成る、識別子必要に応じて、そのメンバーの名前を示す、"="トークンとvariable_initializer (変数の初期化子) により、そのメンバーの初期値。A variable_declarator consists of an identifier that names that member, optionally followed by an "=" token and a variable_initializer (Variable initializers) that gives the initial value of that member.

フィールドは少なくともフィールド自体と同程度にアクセスできる必要があります (アクセシビリティ制約)。The type of a field must be at least as accessible as the field itself (Accessibility constraints).

フィールドの値が使用する式で取得した、 simple_name (簡易名) またはmember_access (メンバー アクセス)。The value of a field is obtained in an expression using a simple_name (Simple names) or a member_access (Member access). 使用して読み取り専用以外のフィールドの値を変更、割り当て(代入演算子)。The value of a non-readonly field is modified using an assignment (Assignment operators). 読み取り専用以外のフィールドの値が取得および変更を使用して後置インクリメントとデクリメント演算子を指定できます (置インクリメント演算子と前置デクリメント演算子) とは、前置インクリメントとデクリメント演算子 (プレフィックスインクリメントおよびデクリメント演算子)。The value of a non-readonly field can be both obtained and modified using postfix increment and decrement operators (Postfix increment and decrement operators) and prefix increment and decrement operators (Prefix increment and decrement operators).

複数のフィールドを宣言するフィールドの宣言は、属性、修飾子、および型の単一のフィールドの複数の宣言と同じです。A field declaration that declares multiple fields is equivalent to multiple declarations of single fields with the same attributes, modifiers, and type. 次に例を示します。For example

class A
{
    public static int X = 1, Y, Z = 100;
}

上記の式は、次の式と同じです。is equivalent to

class A
{
    public static int X = 1;
    public static int Y;
    public static int Z = 100;
}

静的およびインスタンスのフィールドStatic and instance fields

フィールド宣言が含まれています、static修飾子、宣言によって導入されるフィールドは静的フィールドします。When a field declaration includes a static modifier, the fields introduced by the declaration are static fields. ない場合static修飾子が存在する場合、フィールド、宣言によって導入されるインスタンス フィールドします。When no static modifier is present, the fields introduced by the declaration are instance fields. 静的フィールドおよびインスタンス フィールドは、いくつかの種類の変数の 2 つ (変数) で c# の場合は、サポートされているし、も参照されているとして静的変数インスタンス変数、それぞれします。Static fields and instance fields are two of the several kinds of variables (Variables) supported by C#, and at times they are referred to as static variables and instance variables, respectively.

静的フィールドは、特定のインスタンスの一部ではありません。代わりに、クローズ型のすべてのインスタンス間で共有されます (オープンとクローズ型)。A static field is not part of a specific instance; instead, it is shared amongst all instances of a closed type (Open and closed types). 閉じられたクラス型のインスタンスの数が作成されて、関連付けられているアプリケーション ドメインを静的フィールドの 1 つだけのコピーがあります。No matter how many instances of a closed class type are created, there is only ever one copy of a static field for the associated application domain.

例:For example:

class C<V>
{
    static int count = 0;

    public C() {
        count++;
    }

    public static int Count {
        get { return count; }
    }
}

class Application
{
    static void Main() {
        C<int> x1 = new C<int>();
        Console.WriteLine(C<int>.Count);        // Prints 1

        C<double> x2 = new C<double>();
        Console.WriteLine(C<int>.Count);        // Prints 1

        C<int> x3 = new C<int>();
        Console.WriteLine(C<int>.Count);        // Prints 2
    }
}

インスタンス フィールドは、インスタンスに属しています。An instance field belongs to an instance. 具体的には、クラスのすべてのインスタンスには、そのクラスのすべてのインスタンス フィールドの個別のセットが含まれています。Specifically, every instance of a class contains a separate set of all the instance fields of that class.

フィールドが参照されている場合、 member_access (メンバー アクセス) フォームのE.M場合は、M静的フィールド、E含まれる型を表す必要がありますM、場合Mインスタンス フィールドの場合は、電子メールに含まれる型のインスタンスを表す必要がありますMします。When a field is referenced in a member_access (Member access) of the form E.M, if M is a static field, E must denote a type containing M, and if M is an instance field, E must denote an instance of a type containing M.

静的な違いは、インスタンス メンバーの説明とでさらに静的メンバーとインスタンス メンバーThe differences between static and instance members are discussed further in Static and instance members.

読み取り専用フィールドReadonly fields

ときに、 field_declarationが含まれています、readonly修飾子、宣言によって導入されるフィールドは読み取り専用フィールドします。When a field_declaration includes a readonly modifier, the fields introduced by the declaration are readonly fields. 読み取り専用フィールドへの直接代入のみで、インスタンス コンス トラクターまたは同じクラスの静的コンス トラクターまたは宣言の一部として発生します。Direct assignments to readonly fields can only occur as part of that declaration or in an instance constructor or static constructor in the same class. (読み取り専用フィールドはで割り当てられるを複数回これらのコンテキスト。)具体的には、直接割り当てをreadonlyフィールドは、次のコンテキストでのみ許可されます。(A readonly field can be assigned to multiple times in these contexts.) Specifically, direct assignments to a readonly field are permitted only in the following contexts:

  • Variable_declaratorフィールドを導入する (を含めることによって、 variable_initializer宣言内)。In the variable_declarator that introduces the field (by including a variable_initializer in the declaration).
  • インスタンス フィールドのフィールド宣言を含むクラスのインスタンス コンス トラクターで、静的フィールド、フィールド宣言を含むクラスの静的コンス トラクター内。For an instance field, in the instance constructors of the class that contains the field declaration; for a static field, in the static constructor of the class that contains the field declaration. これらは、渡すコンテキストのみでも、readonlyフィールドとして、outまたはrefパラメーター。These are also the only contexts in which it is valid to pass a readonly field as an out or ref parameter.

割り当てる、readonlyフィールドまたはとして渡す、outまたはref他のコンテキストでのパラメーターは、コンパイル時エラー。Attempting to assign to a readonly field or pass it as an out or ref parameter in any other context is a compile-time error.

静的読み取り専用フィールドを使用して、定数Using static readonly fields for constants

Astatic readonlyフィールドが便利な定数値のシンボル名が必要な場合、値の型では使用できません、const宣言、コンパイル時に値を計算できない場合またはします。A static readonly field is useful when a symbolic name for a constant value is desired, but when the type of the value is not permitted in a const declaration, or when the value cannot be computed at compile-time. In the example

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);

    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

BlackWhiteRedGreen、およびBlueメンバーとして宣言できませんconstメンバーのため、コンパイル時にその値を計算することはできません。the Black, White, Red, Green, and Blue members cannot be declared as const members because their values cannot be computed at compile-time. ただし、宣言するstatic readonlyほぼ同じ結果が代わりにします。However, declaring them static readonly instead has much the same effect.

定数と静的読み取り専用フィールドのバージョン管理Versioning of constants and static readonly fields

定数と読み取り専用フィールドは、異なるバイナリのバージョン管理のセマンティクスを持ちます。Constants and readonly fields have different binary versioning semantics. コンパイル時に、定数の値を取得する式は、定数を参照する場合が、式は、読み取り専用フィールドを参照する場合、フィールドの値は実行時まで取得されません。When an expression references a constant, the value of the constant is obtained at compile-time, but when an expression references a readonly field, the value of the field is not obtained until run-time. 2 つのプログラムで構成されるアプリケーションを検討してください。Consider an application that consists of two separate programs:

using System;

namespace Program1
{
    public class Utils
    {
        public static readonly int X = 1;
    }
}

namespace Program2
{
    class Test
    {
        static void Main() {
            Console.WriteLine(Program1.Utils.X);
        }
    }
}

Program1Program2名前空間が個別にコンパイルされる 2 つのプログラムを示します。The Program1 and Program2 namespaces denote two programs that are compiled separately. Program1.Utils.Xによって値の出力は、静的読み取り専用フィールドとして宣言されている、Console.WriteLineステートメントがコンパイル時に、不明はではなく、実行時に取得されます。Because Program1.Utils.X is declared as a static readonly field, the value output by the Console.WriteLine statement is not known at compile-time, but rather is obtained at run-time. そのため場合の値Xが変更されたとProgram1が再コンパイルされる、Console.WriteLineステートメントの出力は、新しい値いてProgram2再コンパイルはありません。Thus, if the value of X is changed and Program1 is recompiled, the Console.WriteLine statement will output the new value even if Program2 isn't recompiled. ただし、 X 、定数の値X時に取得Program2がコンパイルされるとでの変更による影響を受けるに残るProgram1までProgram2が再コンパイルされます。However, had X been a constant, the value of X would have been obtained at the time Program2 was compiled, and would remain unaffected by changes in Program1 until Program2 is recompiled.

Volatile フィールドVolatile fields

ときに、 field_declarationが含まれています、volatile修飾子、宣言によって導入されるフィールドはvolatile フィールドします。When a field_declaration includes a volatile modifier, the fields introduced by that declaration are volatile fields.

非 volatile フィールドの場合は、命令を並べ替える最適化手法をによって提供される同期しないフィールドにアクセスするマルチ スレッド プログラムで、予期しない結果を生じることができます、 lock_statement (Lock ステートメント)。For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the lock_statement (The lock statement). コンパイラによって、実行時のシステムまたはハードウェアは、これらの最適化を実行できます。These optimizations can be performed by the compiler, by the run-time system, or by hardware. Volatile フィールドは、このような並べ替えの最適化が制限されます。For volatile fields, such reordering optimizations are restricted:

  • Volatile フィールドの読み取りと呼ばれる、の volatile 読み取りします。A read of a volatile field is called a volatile read. 揮発性の読み取りが「セマンティクスを取得します。」つまり、メモリへの参照を命令シーケンスで、その後に発生する前に発生するが保証されます。A volatile read has "acquire semantics"; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
  • Volatile フィールドの書き込みと呼ばれる、 volatile 書き込みします。A write of a volatile field is called a volatile write. 揮発性の書き込みが「セマンティクスをリリースします。」つまり、命令シーケンスで書き込み命令の前にメモリ参照の後に発生するが保証されます。A volatile write has "release semantics"; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.

これらの制限により、すべてのスレッドが、他のスレッドによって実行された volatile の書き込みを、実行された順序で観察することが保証されます。These restrictions ensure that all threads will observe volatile writes performed by any other thread in the order in which they were performed. 準拠した実装は、実行のすべてのスレッドから参照できる volatile 書き込みの順序付け単一合計を提供する必要はありません。A conforming implementation is not required to provide a single total ordering of volatile writes as seen from all threads of execution. Volatile フィールドの種類は、次のいずれかである必要があります。The type of a volatile field must be one of the following:

  • A reference_typeします。A reference_type.
  • bytesbyteshortushortintuintcharfloatboolSystem.IntPtr、またはSystem.UIntPtrします。The type byte, sbyte, short, ushort, int, uint, char, float, bool, System.IntPtr, or System.UIntPtr.
  • Enum_typeの基本型を列挙型を持つbytesbyteshortushortint、またはuintします。An enum_type having an enum base type of byte, sbyte, short, ushort, int, or uint.

例では、The example

using System;
using System.Threading;

class Test
{
    public static int result;   
    public static volatile bool finished;

    static void Thread2() {
        result = 143;    
        finished = true; 
    }

    static void Main() {
        finished = false;

        // Run Thread2() in a new thread
        new Thread(new ThreadStart(Thread2)).Start();

        // Wait for Thread2 to signal that it has a result by setting
        // finished to true.
        for (;;) {
            if (finished) {
                Console.WriteLine("result = {0}", result);
                return;
            }
        }
    }
}

この例では、次のように出力されます。produces the output:

result = 143

この例では、メソッドでMainメソッドを実行する新しいスレッドが開始Thread2します。In this example, the method Main starts a new thread that runs the method Thread2. このメソッドは、非揮発性という名前のフィールドに値を格納result、し格納truevolatile フィールドでfinishedします。This method stores a value into a non-volatile field called result, then stores true in the volatile field finished. フィールドのメイン スレッドが待機するfinishedに設定するtrue、フィールドを読み取りますresultします。The main thread waits for the field finished to be set to true, then reads the field result. finishedは宣言されていますvolatile、メイン スレッドが値を読み取る必要があります143フィールドからresultします。Since finished has been declared volatile, the main thread must read the value 143 from the field result. 場合、フィールドfinished宣言されなかったvolatileにストアの許容されることになりますresultに格納した後、メイン スレッドに表示されるfinished、ため、値を読み取るメイン スレッドの0から、フィールドresultします。If the field finished had not been declared volatile, then it would be permissible for the store to result to be visible to the main thread after the store to finished, and hence for the main thread to read the value 0 from the field result. 宣言するfinishedとして、volatileフィールドは、このような不整合を防ぎます。Declaring finished as a volatile field prevents any such inconsistency.

フィールドの初期化Field initialization

フィールドの初期値は静的フィールドまたはインスタンス フィールドであるかどうか、既定値 (既定値) のフィールドの型。The initial value of a field, whether it be a static field or an instance field, is the default value (Default values) of the field's type. この既定の初期化が発生し、フィールドはありません「初期化されていない」したがって前に、フィールドの値を観察することはできません。It is not possible to observe the value of a field before this default initialization has occurred, and a field is thus never "uninitialized". 例では、The example

using System;

class Test
{
    static bool b;
    int i;

    static void Main() {
        Test t = new Test();
        Console.WriteLine("b = {0}, i = {1}", b, t.i);
    }
}

この例では、次のように出力されます。produces the output

b = False, i = 0

biはどちらも自動的に既定値に初期化します。because b and i are both automatically initialized to default values.

変数の初期化子Variable initializers

フィールドの宣言を含めることができますvariable_initializer秒。Field declarations may include variable_initializers. 静的フィールドは、変数の初期化子はクラスの初期化中に実行された代入ステートメントに対応します。For static fields, variable initializers correspond to assignment statements that are executed during class initialization. インスタンス フィールド、変数初期化子に対応クラスのインスタンスが作成されるときに実行されるステートメントを代入します。For instance fields, variable initializers correspond to assignment statements that are executed when an instance of the class is created.

例では、The example

using System;

class Test
{
    static double x = Math.Sqrt(2.0);
    int i = 100;
    string s = "Hello";

    static void Main() {
        Test a = new Test();
        Console.WriteLine("x = {0}, i = {1}, s = {2}", x, a.i, a.s);
    }
}

この例では、次のように出力されます。produces the output

x = 1.4142135623731, i = 100, s = Hello

への代入xが発生した静的フィールド初期化子の実行と、割り当てをisインスタンス フィールド初期化子の実行時に発生します。because an assignment to x occurs when static field initializers execute and assignments to i and s occur when the instance field initializers execute.

説明されている既定値の初期化フィールドの初期化変数初期化子を持つフィールドを含め、すべてのフィールドに発生します。The default value initialization described in Field initialization occurs for all fields, including fields that have variable initializers. したがって、クラスが初期化されると、そのクラス内のすべての静的フィールドは、まず、既定値に初期化し、静的フィールド初期化子は、テキストの順序で実行されます。Thus, when a class is initialized, all static fields in that class are first initialized to their default values, and then the static field initializers are executed in textual order. 同様に、クラスのインスタンスが作成されると、そのインスタンス内のすべてのインスタンス フィールドは、まず、既定値に初期化し、インスタンス フィールド初期化子がテキストの順序で実行します。Likewise, when an instance of a class is created, all instance fields in that instance are first initialized to their default values, and then the instance field initializers are executed in textual order.

既定値の状態で見られる変数初期化子を持つ静的フィールドのことができます。It is possible for static fields with variable initializers to be observed in their default value state. ただし、これは、スタイルの問題として強くお勧めします。However, this is strongly discouraged as a matter of style. 例では、The example

using System;

class Test
{
    static int a = b + 1;
    static int b = a + 1;

    static void Main() {
        Console.WriteLine("a = {0}, b = {1}", a, b);
    }
}

この現象が発生します。exhibits this behavior. 循環定義に関係なく、b、プログラムが無効です。Despite the circular definitions of a and b, the program is valid. 出力になりますIt results in the output

a = 1, b = 2

ため、静的フィールドabに初期化されます0(の既定値int)、初期化子が実行される前にします。because the static fields a and b are initialized to 0 (the default value for int) before their initializers are executed. ときに初期化子aの値を実行します。 b 0 の場合は、のでaに初期化されます1します。When the initializer for a runs, the value of b is zero, and so a is initialized to 1. ときに初期化子bの値を実行します。aは既に1、のでbに初期化されます2します。When the initializer for b runs, the value of a is already 1, and so b is initialized to 2.

静的フィールドの初期化Static field initialization

クラスの静的フィールドの変数初期化子は、一連のクラス宣言に表示されるテキストの順序で実行される割り当てに対応します。The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. 場合、静的コンス トラクター (静的コンス トラクター) が存在する静的フィールド初期化子の実行をクラスでは、その静的コンス トラクターを実行する前に、すぐに発生します。If a static constructor (Static constructors) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. それ以外の場合、静的フィールド初期化子は、そのクラスの静的フィールドの最初に使用する前に、実装に依存する時に実行されます。Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class. 例では、The example

using System;

class Test 
{ 
    static void Main() {
        Console.WriteLine("{0} {1}", B.Y, A.X);
    }

    public static int F(string s) {
        Console.WriteLine(s);
        return 1;
    }
}

class A
{
    public static int X = Test.F("Init A");
}

class B
{
    public static int Y = Test.F("Init B");
}

いずれか、出力を生成する可能性があります。might produce either the output:

Init A
Init B
1 1

または、出力:or the output:

Init B
Init A
1 1

の実行Xの初期化子とYの初期化子は、任意の順序で発生する可能性があります。 これらのフィールドへの参照が発生する限定されます。because the execution of X's initializer and Y's initializer could occur in either order; they are only constrained to occur before the references to those fields. ただしでは、例を示します。However, in the example:

using System;

class Test
{
    static void Main() {
        Console.WriteLine("{0} {1}", B.Y, A.X);
    }

    public static int F(string s) {
        Console.WriteLine(s);
        return 1;
    }
}

class A
{
    static A() {}

    public static int X = Test.F("Init A");
}

class B
{
    static B() {}

    public static int Y = Test.F("Init B");
}

出力があります。the output must be:

Init B
Init A
1 1

ため、静的コンス トラクターが実行する場合の規則 (で定義されている静的コンス トラクター) を提供Bの静的コンス トラクター (したがってBの静的フィールド初期化子)の前に実行する必要がありますAの静的コンス トラクター、フィールド初期化子。because the rules for when static constructors execute (as defined in Static constructors) provide that B's static constructor (and hence B's static field initializers) must run before A's static constructor and field initializers.

インスタンス フィールドの初期化Instance field initialization

クラスのインスタンス フィールド変数初期化子の割り当て時にインスタンス コンス トラクターのいずれかのエントリにすぐに実行されるシーケンスに対応 (コンス トラクター初期化子) そのクラスの。The instance field variable initializers of a class correspond to a sequence of assignments that are executed immediately upon entry to any one of the instance constructors (Constructor initializers) of that class. 変数の初期化子は、クラス宣言に表示されるテキストの順序で実行されます。The variable initializers are executed in the textual order in which they appear in the class declaration. クラスのインスタンスの作成および初期化プロセスの詳細についてはインスタンス コンス トラクターします。The class instance creation and initialization process is described further in Instance constructors.

インスタンス フィールドの変数の初期化子は、作成中のインスタンスを参照できません。A variable initializer for an instance field cannot reference the instance being created. したがって、参照すると、コンパイル時エラーがthis変数の初期化子ではによる任意のインスタンス メンバーを参照する変数の初期化子のコンパイル時エラー、 simple_nameします。Thus, it is a compile-time error to reference this in a variable initializer, as it is a compile-time error for a variable initializer to reference any instance member through a simple_name. In the example

class A
{
    int x = 1;
    int y = x + 1;        // Error, reference to instance member of this
}

変数の初期化子y作成中のインスタンスのメンバーを参照しているため、コンパイル時エラーが発生します。the variable initializer for y results in a compile-time error because it references a member of the instance being created.

メソッドMethods

"メソッド" は、オブジェクトまたはクラスによって実行可能な計算またはアクションを実装するメンバーです。A method is a member that implements a computation or action that can be performed by an object or class. メソッドを使用して宣言method_declaration: %sMethods are declared using method_declarations:

method_declaration
    : method_header method_body
    ;

method_header
    : attributes? method_modifier* 'partial'? return_type member_name type_parameter_list?
      '(' formal_parameter_list? ')' type_parameter_constraints_clause*
    ;

method_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | 'async'
    | method_modifier_unsafe
    ;

return_type
    : type
    | 'void'
    ;

member_name
    : identifier
    | interface_type '.' identifier
    ;

method_body
    : block
    | '=>' expression ';'
    | ';'
    ;

A method_declarationのセットを含めることができます属性(属性) と有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)、 new (new 修飾子)、 static (静的およびインスタンス メソッド)、 virtual (仮想メソッド)、 override (メソッドをオーバーライド)、 sealed (メソッドをシール)、 abstract (抽象メソッド)、およびextern (外部メソッド) 修飾子。A method_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), static (Static and instance methods), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

宣言には、有効な修飾子の組み合わせは、次のすべてに該当する場合。A declaration has a valid combination of modifiers if all of the following are true:

  • 宣言には、有効なアクセス修飾子の組み合わせが含まれています (アクセス修飾子)。The declaration includes a valid combination of access modifiers (Access modifiers).
  • 宣言は含まれません同じ修飾子は、複数回。The declaration does not include the same modifier multiple times.
  • 宣言では、次の修飾子の 1 つだけ含まれています: staticvirtual、およびoverrideします。The declaration includes at most one of the following modifiers: static, virtual, and override.
  • 宣言では、次の修飾子の 1 つだけ含まれています:newoverrideします。The declaration includes at most one of the following modifiers: new and override.
  • 宣言が含まれている場合、abstract修飾子、宣言は次の修飾子のいずれかに含まれません: staticvirtualsealedまたはexternします。If the declaration includes the abstract modifier, then the declaration does not include any of the following modifiers: static, virtual, sealed or extern.
  • 宣言が含まれている場合、private修飾子、宣言は次の修飾子のいずれかに含まれません: virtualoverride、またはabstractします。If the declaration includes the private modifier, then the declaration does not include any of the following modifiers: virtual, override, or abstract.
  • 宣言が含まれている場合、sealed修飾子、宣言も含まれています、override修飾子。If the declaration includes the sealed modifier, then the declaration also includes the override modifier.
  • 宣言が含まれている場合、partial修飾子は、その後は、次の修飾子のいずれかに含まれません: newpublicprotectedinternalprivatevirtualsealedoverrideabstract、またはexternします。If the declaration includes the partial modifier, then it does not include any of the following modifiers: new, public, protected, internal, private, virtual, sealed, override, abstract, or extern.

メソッドを持つ、async修飾子は、非同期関数でありで説明されている規則に従って非同期関数します。A method that has the async modifier is an async function and follows the rules described in Async functions.

Return_typeメソッドの宣言が計算され、メソッドによって返される値の型を指定します。The return_type of a method declaration specifies the type of the value computed and returned by the method. Return_typevoidメソッドが値を返さない場合。The return_type is void if the method does not return a value. 宣言が含まれている場合、partial修飾子は、その戻り値の型である必要がありますvoidします。If the declaration includes the partial modifier, then the return type must be void.

Member_nameメソッドの名前を指定します。The member_name specifies the name of the method. メソッドが明示的なインターフェイス メンバーの実装でない限り (明示的なインターフェイス メンバーの実装)、 member_nameは単に、識別子します。Unless the method is an explicit interface member implementation (Explicit interface member implementations), the member_name is simply an identifier. 明示的なインターフェイス メンバーの実装、 member_nameから成る、 interface_type後に、"."と識別子します。For an explicit interface member implementation, the member_name consists of an interface_type followed by a "." and an identifier.

省略可能なtype_parameter_listメソッドの型パラメーターを指定します (パラメーター入力)。The optional type_parameter_list specifies the type parameters of the method (Type parameters). 場合、 type_parameter_listメソッドが指定されて、ジェネリック メソッドします。If a type_parameter_list is specified the method is a generic method. メソッドの場合、extern修飾子、 type_parameter_listは指定できません。If the method has an extern modifier, a type_parameter_list cannot be specified.

省略可能なformal_parameter_listメソッドのパラメーターを指定します (メソッド パラメーター)。The optional formal_parameter_list specifies the parameters of the method (Method parameters).

省略可能なtype_parameter_constraints_clauseは個々 の型パラメーターの制約を指定する (パラメーターの制約入力) 場合にのみ指定可能性があります、 type_parameter_リストが指定されても、メソッドがないと、override修飾子。The optional type_parameter_constraints_clauses specify constraints on individual type parameters (Type parameter constraints) and may only be specified if a type_parameter_list is also supplied, and the method does not have an override modifier.

Return_typeおよび各で参照される型のformal_parameter_listメソッドは少なくともメソッド自体と同程度にアクセスできる必要があります (アクセシビリティ制約).The return_type and each of the types referenced in the formal_parameter_list of a method must be at least as accessible as the method itself (Accessibility constraints).

Method_bodyがいずれかをセミコロン、ステートメント本体または式本体します。The method_body is either a semicolon, a statement body or an expression body. ステートメント本体から成る、ブロックメソッドが呼び出されたときに実行するステートメントを指定します。A statement body consists of a block, which specifies the statements to execute when the method is invoked. 式の本体から成る=>続けて、およびセミコロンが、メソッドが呼び出されたときに実行する 1 つの式を表します。An expression body consists of => followed by an expression and a semicolon, and denotes a single expression to perform when the method is invoked.

abstractextern、メソッド、 method_bodyセミコロンだけで構成されます。For abstract and extern methods, the method_body consists simply of a semicolon. partialメソッド、 method_bodyのセミコロン、ブロックの本体または式の本体のいずれかで構成されている可能性があります。For partial methods the method_body may consist of either a semicolon, a block body or an expression body. 他のすべてのメソッドに対して、 method_bodyはブロック本体または式の本体。For all other methods, the method_body is either a block body or an expression body.

場合、 method_body 、宣言が含まれていない可能性がありますし、セミコロンから成る、async修飾子。If the method_body consists of a semicolon, then the declaration may not include the async modifier.

名前、型パラメーター リストおよびメソッドの仮パラメーター リストの定義、署名 (シグネチャとオーバー ロード) メソッドの。The name, the type parameter list and the formal parameter list of a method define the signature (Signatures and overloading) of the method. 具体的には、メソッドのシグネチャは、その名前、型パラメーターと数、修飾子、およびその仮パラメーターの型の数で構成されます。Specifically, the signature of a method consists of its name, the number of type parameters and the number, modifiers, and types of its formal parameters. このため、その名前ではなく、メソッドの型引数リストの序数位置を使用して、仮パラメーターの型で使用されるメソッドの型パラメーターが識別されます。戻り値の型はメソッドのシグネチャの一部でないでも、型パラメーターまたは仮パラメーターの名前です。For these purposes, any type parameter of the method that occurs in the type of a formal parameter is identified not by its name, but by its ordinal position in the type argument list of the method.The return type is not part of a method's signature, nor are the names of the type parameters or the formal parameters.

メソッドの名前は、他のすべての非-のメソッドの名前、同じクラスで宣言されているとは異なる必要があります。The name of a method must differ from the names of all other non-methods declared in the same class. さらに、メソッドのシグネチャは、同じクラスで宣言されている他のすべてのメソッドのシグネチャと異なる必要があり、同じクラスで宣言されている 2 つの方法でのみが異なるシグネチャがない可能性がありますrefoutします。In addition, the signature of a method must differ from the signatures of all other methods declared in the same class, and two methods declared in the same class may not have signatures that differ solely by ref and out.

メソッドのtype_parameter全体のスコープでは、 method_declarationでそのスコープ全体でフォームの種類に使用できるとreturn_typemethod_body、およびtype_parameter_constraints_clauses ではなく属性します。The method's type_parameters are in scope throughout the method_declaration, and can be used to form types throughout that scope in return_type, method_body, and type_parameter_constraints_clauses but not in attributes.

すべての仮パラメーターと型パラメーターには、異なる名前がある場合があります。All formal parameters and type parameters must have different names.

メソッドのパラメーターMethod parameters

メソッドのパラメーターは、存在する場合、メソッドの宣言されますformal_parameter_listします。The parameters of a method, if any, are declared by the method's formal_parameter_list.

formal_parameter_list
    : fixed_parameters
    | fixed_parameters ',' parameter_array
    | parameter_array
    ;

fixed_parameters
    : fixed_parameter (',' fixed_parameter)*
    ;

fixed_parameter
    : attributes? parameter_modifier? type identifier default_argument?
    ;

default_argument
    : '=' expression
    ;

parameter_modifier
    : 'ref'
    | 'out'
    | 'this'
    ;

parameter_array
    : attributes? 'params' array_type identifier
    ;

1 つまたは複数コンマ区切りのパラメーターのうち、最後にのみがあります、仮パラメーター リストで構成されます、括らします。The formal parameter list consists of one or more comma-separated parameters of which only the last may be a parameter_array.

A fixed_parameterオプションのセットから成る属性(属性)、省略可能なrefoutまたはthis修飾子、識別子と省略可能なdefault_argumentします。A fixed_parameter consists of an optional set of attributes (Attributes), an optional ref, out or this modifier, a type, an identifier and an optional default_argument. fixed_parameter指定した名前で指定された型のパラメーターを宣言します。Each fixed_parameter declares a parameter of the given type with the given name. this修飾子は、拡張メソッドとしてメソッドを指定しは静的メソッドの最初のパラメーターでのみ使用できます。The this modifier designates the method as an extension method and is only allowed on the first parameter of a static method. 拡張メソッドはさらに「拡張メソッドします。Extension methods are further described in Extension methods.

A fixed_parameterで、 default_argumentと呼ばれますが、省略可能なパラメーターであるのに対し、 fixed_parameter なしdefault_argumentは、必須パラメーターします。A fixed_parameter with a default_argument is known as an optional parameter, whereas a fixed_parameter without a default_argument is a required parameter. 省略可能なパラメーターの後に必要なパラメーターが表示されない、 formal_parameter_listします。A required parameter may not appear after an optional parameter in a formal_parameter_list.

Arefまたはoutパラメーターを含めることはできません、 default_argumentします。A ref or out parameter cannot have a default_argument. で、 default_argument次のいずれかを指定する必要があります。The expression in a default_argument must be one of the following:

  • constant_expressiona constant_expression
  • 式形式のnew S()場所Sは値型です。an expression of the form new S() where S is a value type
  • 式形式のdefault(S)場所Sは値型です。an expression of the form default(S) where S is a value type

id 列またはパラメーターの型を null 許容型の変換によって暗黙的に変換できる必要があります。The expression must be implicitly convertible by an identity or nullable conversion to the type of the parameter.

部分メソッドの実装宣言で省略可能なパラメーターが発生するかどうか (部分メソッド)、明示的なインターフェイス メンバーの実装 (明示的なインターフェイス メンバーの実装) または、パラメーターを 1 つのインデクサーの宣言 (インデクサー) これらのメンバーは、引数を省略を許可する方法では呼び出されませんので、コンパイラは警告を表示する必要があります。If optional parameters occur in an implementing partial method declaration (Partial methods) , an explicit interface member implementation (Explicit interface member implementations) or in a single-parameter indexer declaration (Indexers) the compiler should give a warning, since these members can never be invoked in a way that permits arguments to be omitted.

A括らオプションのセットから成る属性(属性)、params修飾子、 array_type、および識別子します。A parameter_array consists of an optional set of attributes (Attributes), a params modifier, an array_type, and an identifier. パラメーター配列は、指定した名前で指定された配列型の 1 つのパラメーターを宣言します。A parameter array declares a single parameter of the given array type with the given name. Array_type配列パラメーターの 1 次元配列型である必要があります (配列型)。The array_type of a parameter array must be a single-dimensional array type (Array types). メソッドの呼び出しでは、パラメーター配列を指定するには、指定された配列型の 1 つの引数を許可するか、0 個以上の引数を指定する配列要素型のようになります。In a method invocation, a parameter array permits either a single argument of the given array type to be specified, or it permits zero or more arguments of the array element type to be specified. パラメーター配列の詳細についてはパラメーター配列します。Parameter arrays are described further in Parameter arrays.

A括ら、オプションのパラメーターの後に発生する可能性がありますが、既定値は--の引数の省略を含めることはできません、括ら空の配列の作成時に代わりになります。A parameter_array may occur after an optional parameter, but cannot have a default value -- the omission of arguments for a parameter_array would instead result in the creation of an empty array.

次の例は、さまざまな種類のパラメーターを示しています。The following example illustrates different kinds of parameters:

public void M(
    ref int      i,
    decimal      d,
    bool         b = false,
    bool?        n = false,
    string       s = "Hello",
    object       o = null,
    T            t = default(T),
    params int[] a
) { }

Formal_parameter_listMi必要な ref パラメーターでは、dが必要な値を持つパラメーター、 bsotパラメーターが省略可能な値とaはパラメーター配列です。In the formal_parameter_list for M, i is a required ref parameter, d is a required value parameter, b, s, o and t are optional value parameters and a is a parameter array.

メソッドの宣言では、パラメーター、型パラメーターとローカル変数を別の宣言領域を作成します。A method declaration creates a separate declaration space for parameters, type parameters and local variables. ローカル変数宣言と型パラメーター リストと、メソッドの仮パラメーター リストで、この宣言領域に名前が導入された、ブロックメソッドの。Names are introduced into this declaration space by the type parameter list and the formal parameter list of the method and by local variable declarations in the block of the method. メソッドの宣言領域に同じ名前の 2 つのメンバーのエラーになります。It is an error for two members of a method declaration space to have the same name. メソッドの宣言領域と同じ名前の要素を格納する入れ子になった宣言領域のローカル変数の宣言領域のエラーになります。It is an error for the method declaration space and the local variable declaration space of a nested declaration space to contain elements with the same name.

メソッドの呼び出し (メソッドの呼び出し) その呼び出しに固有のコピーが作成、仮パラメーターと、メソッドのローカル変数と呼び出しの引数リストの値または変数の参照に割り当てられます、仮パラメーターを新しく作成します。A method invocation (Method invocations) creates a copy, specific to that invocation, of the formal parameters and local variables of the method, and the argument list of the invocation assigns values or variable references to the newly created formal parameters. 内で、ブロックでそれらの識別子で、メソッドの仮パラメーターを参照できるsimple_name式 (簡易名)。Within the block of a method, formal parameters can be referenced by their identifiers in simple_name expressions (Simple names).

仮パラメーターの 4 つの種類があります。There are four kinds of formal parameters:

  • 値パラメーターは、修飾子なしで宣言されます。Value parameters, which are declared without any modifiers.
  • 宣言されるパラメーターを参照して、ref修飾子。Reference parameters, which are declared with the ref modifier.
  • 宣言される出力パラメーター、out修飾子。Output parameters, which are declared with the out modifier.
  • 宣言されるパラメーター配列、params修飾子。Parameter arrays, which are declared with the params modifier.

」の説明に従ってシグネチャとオーバー ロードrefout修飾子はメソッドのシグネチャの一部が、params修飾子はありません。As described in Signatures and overloading, the ref and out modifiers are part of a method's signature, but the params modifier is not.

値パラメーターValue parameters

修飾子なしで宣言されたパラメーターは、値パラメーターです。A parameter declared with no modifiers is a value parameter. 値を持つパラメーターは、メソッドの呼び出しで指定された対応する引数からその初期値を取得するローカル変数に対応します。A value parameter corresponds to a local variable that gets its initial value from the corresponding argument supplied in the method invocation.

メソッドの呼び出しで、対応する引数が暗黙的に変換できる式を指定する必要があります仮パラメーターに値を持つパラメーターがある場合 (暗黙的な変換) 仮パラメーターの型にします。When a formal parameter is a value parameter, the corresponding argument in a method invocation must be an expression that is implicitly convertible (Implicit conversions) to the formal parameter type.

値を持つパラメーターに新しい値を割り当てるメソッドが許可されます。A method is permitted to assign new values to a value parameter. このような割り当て、value パラメーターで表されるローカル ストレージの場所にのみ影響: メソッドの呼び出しで指定された実際の引数には影響があるありません。Such assignments only affect the local storage location represented by the value parameter—they have no effect on the actual argument given in the method invocation.

参照パラメーターReference parameters

宣言したパラメーターをref修飾子は、参照パラメーター。A parameter declared with a ref modifier is a reference parameter. 値パラメーターの場合とは異なり、参照パラメーターは、新しい記憶域の場所を作成できません。Unlike a value parameter, a reference parameter does not create a new storage location. 代わりに、参照パラメーターは、メソッドの呼び出しで引数として指定された変数と同じストレージ場所を表します。Instead, a reference parameter represents the same storage location as the variable given as the argument in the method invocation.

メソッドの呼び出しで対応する引数がキーワードで構成される必要があります仮パラメーターは、参照パラメーターが、ref続けて、 variable_reference (を決定するための厳密な規則確実な代入) の仮パラメーターと同じ型。When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable_reference (Precise rules for determining definite assignment) of the same type as the formal parameter. 参照パラメーターとして渡す前に、変数を間違いなく割り当てる必要があります。A variable must be definitely assigned before it can be passed as a reference parameter.

メソッド内の参照パラメーターは常と見なされます明示的に代入します。Within a method, a reference parameter is always considered definitely assigned.

反復子として宣言されたメソッド (反復子) 参照パラメーターを含めることはできません。A method declared as an iterator (Iterators) cannot have reference parameters.

例では、The example

using System;

class Test
{
    static void Swap(ref int x, ref int y) {
        int temp = x;
        x = y;
        y = temp;
    }

    static void Main() {
        int i = 1, j = 2;
        Swap(ref i, ref j);
        Console.WriteLine("i = {0}, j = {1}", i, j);
    }
}

この例では、次のように出力されます。produces the output

i = 2, j = 1

呼び出しのSwapMainx表しますiy表しますjFor the invocation of Swap in Main, x represents i and y represents j. このため、呼び出しは、の値を交換ijします。Thus, the invocation has the effect of swapping the values of i and j.

メソッドでは複数の名前が同じ記憶域の場所を表すことが参照パラメーターを受け取る。In a method that takes reference parameters it is possible for multiple names to represent the same storage location. In the example

class A
{
    string s;

    void F(ref string a, ref string b) {
        s = "One";
        a = "Two";
        b = "Three";
    }

    void G() {
        F(ref s, ref s);
    }
}

呼び出しFGへの参照を渡すs両方のabします。the invocation of F in G passes a reference to s for both a and b. したがって、その呼び出しでは、名前のsa、およびbすべて、同じストレージの場所を参照し、すべての 3 つの割り当ては、インスタンス フィールドを変更sします。Thus, for that invocation, the names s, a, and b all refer to the same storage location, and the three assignments all modify the instance field s.

出力パラメーターOutput parameters

宣言したパラメーター、out修飾子は、出力パラメーター。A parameter declared with an out modifier is an output parameter. 参照パラメーターと同様に、出力パラメーターには新しい記憶域の場所は作成できません。Similar to a reference parameter, an output parameter does not create a new storage location. 代わりに、出力パラメーターは、メソッドの呼び出しで引数として指定された変数と同じストレージ場所を表します。Instead, an output parameter represents the same storage location as the variable given as the argument in the method invocation.

メソッドの呼び出しで対応する引数がキーワードで構成される必要があります仮パラメーターが出力パラメーターの場合は、out続けて、 variable_reference (を決定するための厳密な規則確実な代入) の仮パラメーターと同じ型。When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable_reference (Precise rules for determining definite assignment) of the same type as the formal parameter. 変数必要がありますいないに明示的に代入、出力パラメーターとして渡すことが、次の変数が出力パラメーターとして渡された呼び出し、変数と見なされます明示的に代入します。A variable need not be definitely assigned before it can be passed as an output parameter, but following an invocation where a variable was passed as an output parameter, the variable is considered definitely assigned.

メソッド内と同じように、ローカル変数、出力パラメーターは最初と見なされる未割り当ての値を使用する前に間違いなく割り当てる必要があります。Within a method, just like a local variable, an output parameter is initially considered unassigned and must be definitely assigned before its value is used.

メソッドが戻る前に、メソッドのすべての出力パラメーターを間違いなく割り当てる必要があります。Every output parameter of a method must be definitely assigned before the method returns.

部分メソッドとして宣言されたメソッド (部分メソッド) または反復子 (反復子) パラメーターの出力があることはできません。A method declared as a partial method (Partial methods) or an iterator (Iterators) cannot have output parameters.

出力パラメーターは、複数の戻り値を生成するメソッドで通常使用されます。Output parameters are typically used in methods that produce multiple return values. 例:For example:

using System;

class Test
{
    static void SplitPath(string path, out string dir, out string name) {
        int i = path.Length;
        while (i > 0) {
            char ch = path[i - 1];
            if (ch == '\\' || ch == '/' || ch == ':') break;
            i--;
        }
        dir = path.Substring(0, i);
        name = path.Substring(i);
    }

    static void Main() {
        string dir, name;
        SplitPath("c:\\Windows\\System\\hello.txt", out dir, out name);
        Console.WriteLine(dir);
        Console.WriteLine(name);
    }
}

この例では、出力が生成されます。The example produces the output:

c:\Windows\System\
hello.txt

なお、dirnameに渡す前に変数が割り当て済みにすることができますSplitPath、いると見なされる次の呼び出しが明示的に代入するとします。Note that the dir and name variables can be unassigned before they are passed to SplitPath, and that they are considered definitely assigned following the call.

パラメーター配列Parameter arrays

宣言したパラメーターをparams修飾子は、パラメーター配列。A parameter declared with a params modifier is a parameter array. 仮パラメーター リストには、パラメーター配列が含まれている場合、一覧の最後のパラメーターがあり、1 次元配列型でなければなりません。If a formal parameter list includes a parameter array, it must be the last parameter in the list and it must be of a single-dimensional array type. たとえば、型string[]string[][]パラメーター配列の型が、型として使用できるstring[,]ことはできません。For example, the types string[] and string[][] can be used as the type of a parameter array, but the type string[,] can not. 結合することはできません、params修飾子を使用して修飾子refoutします。It is not possible to combine the params modifier with the modifiers ref and out.

パラメーター配列は、メソッドの呼び出しで 2 つの方法のいずれかで指定する引数を許可します。A parameter array permits arguments to be specified in one of two ways in a method invocation:

  • 引数の指定されたパラメーター配列は、暗黙的に変換する 1 つの式を指定できます (暗黙的な変換) に、パラメーター配列の型。The argument given for a parameter array can be a single expression that is implicitly convertible (Implicit conversions) to the parameter array type. この場合、パラメーター配列は、値を持つパラメーターとまったく同じように機能します。In this case, the parameter array acts precisely like a value parameter.
  • または、呼び出しはそれぞれの引数が、暗黙的に変換する式は、パラメーター配列の 0 個以上の引数を指定できます (暗黙的な変換) パラメーターの配列の要素の型にします。Alternatively, the invocation can specify zero or more arguments for the parameter array, where each argument is an expression that is implicitly convertible (Implicit conversions) to the element type of the parameter array. ここでは、呼び出し引数の数に対応する長さを持つパラメーターの配列型のインスタンスを作成します。 指定された引数に値を使用して、配列インスタンスの要素を初期化し、実際に新しく作成された配列のインスタンスを使用引数。In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument.

を除き、呼び出しの可変個の引数を許可すると、パラメーター配列に値を持つパラメーターとまったく同じです (パラメーターの値) 同じ型。Except for allowing a variable number of arguments in an invocation, a parameter array is precisely equivalent to a value parameter (Value parameters) of the same type.

例では、The example

using System;

class Test
{
    static void F(params int[] args) {
        Console.Write("Array contains {0} elements:", args.Length);
        foreach (int i in args) 
            Console.Write(" {0}", i);
        Console.WriteLine();
    }

    static void Main() {
        int[] arr = {1, 2, 3};
        F(arr);
        F(10, 20, 30, 40);
        F();
    }
}

この例では、次のように出力されます。produces the output

Array contains 3 elements: 1 2 3
Array contains 4 elements: 10 20 30 40
Array contains 0 elements:

最初の呼び出しF配列を渡すだけa値パラメーターとして。The first invocation of F simply passes the array a as a value parameter. 2 番目の呼び出しのF4 つの要素が自動的に作成int[]の特定の要素の値と配列のインスタンスの値を持つパラメーターとして渡します。The second invocation of F automatically creates a four-element int[] with the given element values and passes that array instance as a value parameter. 3 つ目の呼び出しでは同様に、 F 0 要素を作成しますint[]値パラメーターとしてそのインスタンスを渡します。Likewise, the third invocation of F creates a zero-element int[] and passes that instance as a value parameter. 2 番目と 3 番目の呼び出しは、書き込みを正確に同じです。The second and third invocations are precisely equivalent to writing:

F(new int[] {10, 20, 30, 40});
F(new int[] {});

パラメーター配列を持つメソッドを標準形式で、または拡張形式では、適用可能なオーバー ロードの解決を実行するときに (適用可能な関数メンバー)。When performing overload resolution, a method with a parameter array may be applicable either in its normal form or in its expanded form (Applicable function member). メソッドの拡張の形式は、通常、メソッドの形式が適用されない場合にのみ、および拡張形式と同じシグネチャを持つ、該当するメソッドが同じ型で既に宣言されていない場合にのみ使用できます。The expanded form of a method is available only if the normal form of the method is not applicable and only if an applicable method with the same signature as the expanded form is not already declared in the same type.

例では、The example

using System;

class Test
{
    static void F(params object[] a) {
        Console.WriteLine("F(object[])");
    }

    static void F() {
        Console.WriteLine("F()");
    }

    static void F(object a0, object a1) {
        Console.WriteLine("F(object,object)");
    }

    static void Main() {
        F();
        F(1);
        F(1, 2);
        F(1, 2, 3);
        F(1, 2, 3, 4);
    }
}

この例では、次のように出力されます。produces the output

F();
F(object[]);
F(object,object);
F(object[]);
F(object[]);

例では、パラメーター配列を持つメソッドの拡張可能な形式の 2 つ既に含まれているクラスの通常のメソッドとして。In the example, two of the possible expanded forms of the method with a parameter array are already included in the class as regular methods. そのため、これらの拡張形式はオーバー ロードの解決を実行するときに考慮されませんし、最初と 3 番目のメソッドの呼び出しでは、通常のメソッドが選択します。These expanded forms are therefore not considered when performing overload resolution, and the first and third method invocations thus select the regular methods. クラスは、パラメーター配列を持つメソッドを宣言して、それはも通常のメソッドとして展開されたフォームの一部を含めるには珍しくありません。When a class declares a method with a parameter array, it is not uncommon to also include some of the expanded forms as regular methods. により、配列の割り当てを回避することは、パラメーター配列を持つメソッドの拡張の形式のときに発生するインスタンスが呼び出されます。By doing so it is possible to avoid the allocation of an array instance that occurs when an expanded form of a method with a parameter array is invoked.

パラメーター配列の型の場合はobject[]、通常、メソッドの形式と単一の拡張形式の間で発生する潜在的なあいまいさobjectパラメーター。When the type of a parameter array is object[], a potential ambiguity arises between the normal form of the method and the expended form for a single object parameter. あいまいさの理由は、object[]型に暗黙的に変換自体がobjectします。The reason for the ambiguity is that an object[] is itself implicitly convertible to type object. あいまいさも問題はありません、ただし、必要な場合は、キャストを挿入することで解決できるためです。The ambiguity presents no problem, however, since it can be resolved by inserting a cast if needed.

例では、The example

using System;

class Test
{
    static void F(params object[] args) {
        foreach (object o in args) {
            Console.Write(o.GetType().FullName);
            Console.Write(" ");
        }
        Console.WriteLine();
    }

    static void Main() {
        object[] a = {1, "Hello", 123.456};
        object o = a;
        F(a);
        F((object)a);
        F(o);
        F((object[])o);
    }
}

この例では、次のように出力されます。produces the output

System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double

最初と最後の呼び出しでF、通常の形式Fはパラメーターの型に引数の型からの暗黙的な変換が存在するために適用 (型の両方がobject[])。In the first and last invocations of F, the normal form of F is applicable because an implicit conversion exists from the argument type to the parameter type (both are of type object[]). したがって、オーバー ロードの解決は通常の形式を選択します。 F、通常の値のパラメーターとして渡される引数、と。Thus, overload resolution selects the normal form of F, and the argument is passed as a regular value parameter. 2 番目と 3 番目の呼び出し、通常の形式でF暗黙的な変換が存在しないため、引数の型からパラメーターの型には適用できません (型object型に暗黙的に変換できないobject[])。In the second and third invocations, the normal form of F is not applicable because no implicit conversion exists from the argument type to the parameter type (type object cannot be implicitly converted to type object[]). ただし、拡張されたフォームのFはオーバー ロードの解決で選択されているので、該当します。However, the expanded form of F is applicable, so it is selected by overload resolution. その結果、1 つの要素object[]、呼び出しによって作成し、配列の 1 つの要素が指定された引数の値で初期化されます (への参照をそれ自体が、 object[])。As a result, a one-element object[] is created by the invocation, and the single element of the array is initialized with the given argument value (which itself is a reference to an object[]).

静的メソッドとインスタンス メソッドStatic and instance methods

メソッドの宣言が含まれています、static修飾子、メソッドは静的メソッドをいいます。When a method declaration includes a static modifier, that method is said to be a static method. ない場合static修飾子が存在する、メソッドはインスタンス メソッドと呼ばれます。When no static modifier is present, the method is said to be an instance method.

静的メソッドは、特定のインスタンスでは動作せずを参照すると、コンパイル時エラーthisで静的メソッド。A static method does not operate on a specific instance, and it is a compile-time error to refer to this in a static method.

インスタンス メソッドは、クラスの特定のインスタンスを操作し、そのインスタンスとしてアクセスできますthis(このアクセス)。An instance method operates on a given instance of a class, and that instance can be accessed as this (This access).

メソッドが参照されている場合、 member_access (メンバー アクセス) フォームのE.M場合は、M静的メソッドでは、 E を含む型を表す必要がありますM、場合M、インスタンス メソッドであるE含まれる型のインスタンスを表す必要がありますMします。When a method is referenced in a member_access (Member access) of the form E.M, if M is a static method, E must denote a type containing M, and if M is an instance method, E must denote an instance of a type containing M.

静的な違いは、インスタンス メンバーの説明とでさらに静的メンバーとインスタンス メンバーThe differences between static and instance members are discussed further in Static and instance members.

仮想メソッドVirtual methods

インスタンス メソッドの宣言が含まれています、virtual修飾子、メソッドは仮想メソッドをいいます。When an instance method declaration includes a virtual modifier, that method is said to be a virtual method. ない場合virtual修飾子が存在する、メソッドは、非仮想メソッドと呼ばれます。When no virtual modifier is present, the method is said to be a non-virtual method.

非仮想メソッドの実装は、バリアントではありません。内のクラスのインスタンスでメソッドが呼び出されるかどうか、実装は同じ宣言されているか、派生クラスのインスタンス。The implementation of a non-virtual method is invariant: The implementation is the same whether the method is invoked on an instance of the class in which it is declared or an instance of a derived class. これに対し、仮想メソッドの実装は、派生クラスで置き換えることができます。In contrast, the implementation of a virtual method can be superseded by derived classes. 継承された仮想メソッドの実装に取り替えるのプロセスと呼びますオーバーライドメソッド (メソッドをオーバーライド)。The process of superseding the implementation of an inherited virtual method is known as overriding that method (Override methods).

仮想メソッドの呼び出しで、実行時の型その呼び出しが対象のインスタンスの場所は、実際のメソッドの実装を呼び出すを決定します。In a virtual method invocation, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke. 非仮想メソッドの呼び出しで、コンパイル時の型インスタンスの決定要因は、します。In a non-virtual method invocation, the compile-time type of the instance is the determining factor. 正確には、メソッドがという名前でNが呼び出されると、引数リストAコンパイル時の型を持つインスタンスでCと実行時の型R(場所RC派生したクラスまたはC)、呼び出しは次のように処理されます。In precise terms, when a method named N is invoked with an argument list A on an instance with a compile-time type C and a run-time type R (where R is either C or a class derived from C), the invocation is processed as follows:

  • オーバー ロードの解決を適用する最初に、 CN、およびA、特定の方法を選択するMで宣言および継承されるメソッドのセットからCします。First, overload resolution is applied to C, N, and A, to select a specific method M from the set of methods declared in and inherited by C. メソッドの呼び出しします。This is described in Method invocations.
  • その後、ifM非仮想メソッドでは、Mが呼び出されます。Then, if M is a non-virtual method, M is invoked.
  • それ以外の場合、Mは仮想メソッド、および、最派生実装のMRが呼び出されます。Otherwise, M is a virtual method, and the most derived implementation of M with respect to R is invoked.

宣言またはクラスによって継承されている仮想メソッドのそれぞれについて、存在、最も派生実装そのクラスに対してメソッドの。For every virtual method declared in or inherited by a class, there exists a most derived implementation of the method with respect to that class. 仮想メソッドの最多派生実装Mクラスに関してRは次のように決定されます。The most derived implementation of a virtual method M with respect to a class R is determined as follows:

  • 場合R、導入が含まれています。virtualの宣言M、これは、最派生実装のMします。If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
  • の場合Rが含まれています、overrideM、これは、最派生実装のMします。Otherwise, if R contains an override of M, then this is the most derived implementation of M.
  • それ以外の場合の実装の派生を最大限にMRは、最派生実装のと同じMの直接の基本クラスに対してROtherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.

次の例は、仮想および非仮想メソッドの違いを示しています。The following example illustrates the differences between virtual and non-virtual methods:

using System;

class A
{
    public void F() { Console.WriteLine("A.F"); }

    public virtual void G() { Console.WriteLine("A.G"); }
}

class B: A
{
    new public void F() { Console.WriteLine("B.F"); }

    public override void G() { Console.WriteLine("B.G"); }
}

class Test
{
    static void Main() {
        B b = new B();
        A a = b;
        a.F();
        b.F();
        a.G();
        b.G();
    }
}

例では、A非仮想メソッドを導入Fと仮想メソッドGします。In the example, A introduces a non-virtual method F and a virtual method G. クラスは、B新しい非仮想メソッドが導入されていますF、そのため、継承を非表示F、継承されたメソッドもオーバーライドとGします。The class B introduces a new non-virtual method F, thus hiding the inherited F, and also overrides the inherited method G. この例では、出力が生成されます。The example produces the output:

A.F
B.F
B.G
B.G

注意ステートメントa.G()呼び出すB.Gではなく、A.Gします。Notice that the statement a.G() invokes B.G, not A.G. これは、実行時の型のインスタンスのためです (これはB)、インスタンスのコンパイル時型ではありません (これはA) を呼び出す実際のメソッドの実装を決定します。This is because the run-time type of the instance (which is B), not the compile-time type of the instance (which is A), determines the actual method implementation to invoke.

継承されたメソッドを非表示には、メソッドが許可されている、ために、同じシグネチャを持つ複数の仮想メソッドを含むクラス可能性があります。Because methods are allowed to hide inherited methods, it is possible for a class to contain several virtual methods with the same signature. 最派生メソッドを除くすべてが非表示のため、あいまいさの問題は発生このしません。This does not present an ambiguity problem, since all but the most derived method are hidden. In the example

using System;

class A
{
    public virtual void F() { Console.WriteLine("A.F"); }
}

class B: A
{
    public override void F() { Console.WriteLine("B.F"); }
}

class C: B
{
    new public virtual void F() { Console.WriteLine("C.F"); }
}

class D: C
{
    public override void F() { Console.WriteLine("D.F"); }
}

class Test
{
    static void Main() {
        D d = new D();
        A a = d;
        B b = d;
        C c = d;
        a.F();
        b.F();
        c.F();
        d.F();
    }
}

CDクラスに同じシグネチャを持つ 2 つの仮想メソッドを含めます。導入された、1 つAで導入された、1 つCします。the C and D classes contain two virtual methods with the same signature: The one introduced by A and the one introduced by C. 導入されたメソッドCから継承されたメソッドを非表示にAします。The method introduced by C hides the method inherited from A. オーバーライド宣言つまりDで導入されたメソッドをオーバーライドCのことはできませんとDで導入されたメソッドをオーバーライドするAThus, the override declaration in D overrides the method introduced by C, and it is not possible for D to override the method introduced by A. この例では、出力が生成されます。The example produces the output:

B.F
B.F
D.F
D.F

インスタンスへのアクセスによって非表示の仮想メソッドを呼び出すことはD小から派生した型、メソッドが非表示されません。Note that it is possible to invoke the hidden virtual method by accessing an instance of D through a less derived type in which the method is not hidden.

メソッドをオーバーライドします。Override methods

インスタンス メソッドの宣言が含まれています、override修飾子、メソッドはモード、メソッドをオーバーライドしてします。When an instance method declaration includes an override modifier, the method is said to be an override method. オーバーライド メソッドでは、同じシグネチャを持つ継承された仮想メソッドをオーバーライドします。An override method overrides an inherited virtual method with the same signature. 仮想メソッドの宣言には新しいメソッドが導入されていますが、オーバーライド メソッドの宣言では、そのメソッドの新しい実装を提供することで既存の継承された仮想メソッドを特殊化します。Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

によってオーバーライドされたメソッド、override宣言と呼ばれる、基本メソッドをオーバーライドします。The method overridden by an override declaration is known as the overridden base method. オーバーライド メソッドMクラスで宣言されているC、オーバーライドされる基本メソッドはの各基本クラス型を調べることによって決まりますCの直接基底クラスの型と、C進みながら連続します。直接の基本クラスの型が指定された基本クラス型であるアクセス可能なメソッドは、少なくとも 1 つまでと同じシグネチャを持つM型引数の置換後にします。For an override method M declared in a class C, the overridden base method is determined by examining each base class type of C, starting with the direct base class type of C and continuing with each successive direct base class type, until in a given base class type at least one accessible method is located which has the same signature as M after substitution of type arguments. オーバーライドされる基本メソッドを検索するためには、メソッドと見なされますがある場合は、アクセスpublicである場合、protectedである場合、protected internalである場合またはinternalとして同じプログラム内で宣言されているとCします。For the purposes of locating the overridden base method, a method is considered accessible if it is public, if it is protected, if it is protected internal, or if it is internal and declared in the same program as C.

上書きの宣言の場合は true、次のすべての場合を除いて、コンパイル時エラーが発生します。A compile-time error occurs unless all of the following are true for an override declaration:

  • 前述のように配置されている、オーバーライドされる基本メソッドは使用できます。An overridden base method can be located as described above.
  • このようなオーバーライドされる基本メソッドは 1 つだけです。There is exactly one such overridden base method. この制限は、基本クラスの型が構築された型、型引数の置換により 2 つのメソッドのシグネチャと同じ場合にのみ影響です。This restriction has effect only if the base class type is a constructed type where the substitution of type arguments makes the signature of two methods the same.
  • オーバーライドされる基本メソッドが仮想、抽象型の場合、またはメソッドをオーバーライドします。The overridden base method is a virtual, abstract, or override method. つまり、オーバーライドされる基本メソッドは、静的または非仮想にすることはできません。In other words, the overridden base method cannot be static or non-virtual.
  • オーバーライドの基本メソッドは、シール メソッドではありません。The overridden base method is not a sealed method.
  • オーバーライド メソッドとオーバーライドされる基本メソッドと同じ戻り値型であります。The override method and the overridden base method have the same return type.
  • オーバーライドされる基本メソッドとオーバーライド宣言は、同じの宣言されたアクセシビリティを持ちます。The override declaration and the overridden base method have the same declared accessibility. つまり、オーバーライド宣言は、仮想メソッドのアクセシビリティを変更することはできません。In other words, an override declaration cannot change the accessibility of the virtual method. ただし、オーバーライドされる基本メソッドの内部が保護されており、オーバーライド メソッド、オーバーライド メソッドを含むアセンブリが宣言されているよりもに、別のアセンブリで宣言されている場合は、アクセシビリティを保護されなければなりません。However, if the overridden base method is protected internal and it is declared in a different assembly than the assembly containing the override method then the override method's declared accessibility must be protected.
  • オーバーライドの宣言では、型パラメーター制約句が指定されていません。The override declaration does not specify type-parameter-constraints-clauses. 代わりに、制約は、オーバーライドされる基本メソッドから継承されます。Instead the constraints are inherited from the overridden base method. オーバーライドされたメソッドの型パラメーターの制約を型引数は、継承された制約に置き換えることができますに注意してください。Note that constraints that are type parameters in the overridden method may be replaced by type arguments in the inherited constraint. これは、法的なは、値の型または sealed 型など、明示的に指定されている制約につながります。This can lead to constraints that are not legal when explicitly specified, such as value types or sealed types.

次の例では、ジェネリック クラスのオーバーライドの規則のしくみを示しています。The following example demonstrates how the overriding rules work for generic classes:

abstract class C<T>
{
    public virtual T F() {...}
    public virtual C<T> G() {...}
    public virtual void H(C<T> x) {...}
}

class D: C<string>
{
    public override string F() {...}            // Ok
    public override C<string> G() {...}         // Ok
    public override void H(C<T> x) {...}        // Error, should be C<string>
}

class E<T,U>: C<U>
{
    public override U F() {...}                 // Ok
    public override C<U> G() {...}              // Ok
    public override void H(C<T> x) {...}        // Error, should be C<U>
}

オーバーライド宣言は、オーバーライドされる基本メソッドを使用して、アクセスできる、 base_access (Base アクセス)。An override declaration can access the overridden base method using a base_access (Base access). In the example

class A
{
    int x;

    public virtual void PrintFields() {
        Console.WriteLine("x = {0}", x);
    }
}

class B: A
{
    int y;

    public override void PrintFields() {
        base.PrintFields();
        Console.WriteLine("y = {0}", y);
    }
}

base.PrintFields()で呼び出しB呼び出す、PrintFieldsメソッドで宣言Aします。the base.PrintFields() invocation in B invokes the PrintFields method declared in A. A base_access仮想呼び出しメカニズムを無効にし、単に基本のメソッドを非仮想メソッドとして扱われます。A base_access disables the virtual invocation mechanism and simply treats the base method as a non-virtual method. 呼び出す必要があるBされて書き込まれる((A)this).PrintFields()、再帰的に存在するかを呼び出す、PrintFieldsメソッドで宣言Bで宣言されている 1 つではないA、ためPrintFields仮想の実行時の型と((A)this)Bします。Had the invocation in B been written ((A)this).PrintFields(), it would recursively invoke the PrintFields method declared in B, not the one declared in A, since PrintFields is virtual and the run-time type of ((A)this) is B.

含めることによってのみ、override修飾子は、メソッドは、別のメソッドをオーバーライドします。Only by including an override modifier can a method override another method. その他のすべてのケースで、継承されたメソッドとして同じシグネチャを持つメソッドは単に継承されたメソッドを隠ぺいします。In all other cases, a method with the same signature as an inherited method simply hides the inherited method. In the example

class A
{
    public virtual void F() {}
}

class B: A
{
    public virtual void F() {}        // Warning, hiding inherited F()
}

FメソッドBは含まれません、override修飾子を上書きしませんし、FメソッドAします。the F method in B does not include an override modifier and therefore does not override the F method in A. 代わりに、FメソッドBでメソッドを非表示にA、宣言が含まれていないために、警告が報告されると、new修飾子。Rather, the F method in B hides the method in A, and a warning is reported because the declaration does not include a new modifier.

In the example

class A
{
    public virtual void F() {}
}

class B: A
{
    new private void F() {}        // Hides A.F within body of B
}

class C: B
{
    public override void F() {}    // Ok, overrides A.F
}

FメソッドB仮想を非表示にFから継承されたメソッドAします。the F method in B hides the virtual F method inherited from A. 以降、新しいFBプライベート アクセスは、そのスコープには、のクラスの本文にはのみが含まれます。Bには拡張されませんとCします。Since the new F in B has private access, its scope only includes the class body of B and does not extend to C. 宣言ではそのため、FC上書きが許可されている、Fから継承されたAします。Therefore, the declaration of F in C is permitted to override the F inherited from A.

シール メソッドSealed methods

インスタンス メソッドの宣言が含まれています、sealed修飾子、メソッドがあると言うこと、メソッドをシールします。When an instance method declaration includes a sealed modifier, that method is said to be a sealed method. インスタンス メソッドの宣言が含まれている場合、sealed修飾子も含める必要があります、override修飾子。If an instance method declaration includes the sealed modifier, it must also include the override modifier. 使用、sealed修飾子からさらに、メソッドをオーバーライドする派生クラスをできないようにします。Use of the sealed modifier prevents a derived class from further overriding the method.

In the example

using System;

class A
{
    public virtual void F() {
        Console.WriteLine("A.F");
    }

    public virtual void G() {
        Console.WriteLine("A.G");
    }
}

class B: A
{
    sealed override public void F() {
        Console.WriteLine("B.F");
    } 

    override public void G() {
        Console.WriteLine("B.G");
    } 
}

class C: B
{
    override public void G() {
        Console.WriteLine("C.G");
    } 
}

クラスは、 B 2 つのメソッドのオーバーライドは、:Fメソッドを持つ、sealed修飾子とGメソッドにはないです。the class B provides two override methods: an F method that has the sealed modifier and a G method that does not. B使用が、シールドのmodifier防止CをさらにオーバーライドFします。B's use of the sealed modifier prevents C from further overriding F.

抽象メソッドAbstract methods

インスタンス メソッドの宣言が含まれています、abstract修飾子、メソッドがあると言うこと、抽象メソッドします。When an instance method declaration includes an abstract modifier, that method is said to be an abstract method. 抽象メソッドは暗黙的にも仮想メソッドの修飾子を持つことはできませんvirtualします。Although an abstract method is implicitly also a virtual method, it cannot have the modifier virtual.

抽象メソッドの宣言では、新しい仮想メソッドが導入されていますが、そのメソッドの実装は提供されません。An abstract method declaration introduces a new virtual method but does not provide an implementation of that method. 代わりに、非抽象派生クラスでは、そのメソッドをオーバーライドすることで独自の実装を提供する必要があります。Instead, non-abstract derived classes are required to provide their own implementation by overriding that method. 抽象メソッドが実際の実装を提供しないため、 method_bodyの抽象メソッドをセミコロンの構成だけです。Because an abstract method provides no actual implementation, the method_body of an abstract method simply consists of a semicolon.

抽象メソッドの宣言は抽象クラスでのみ許可されます (抽象クラス)。Abstract method declarations are only permitted in abstract classes (Abstract classes).

In the example

public abstract class Shape
{
    public abstract void Paint(Graphics g, Rectangle r);
}

public class Ellipse: Shape
{
    public override void Paint(Graphics g, Rectangle r) {
        g.DrawEllipse(r);
    }
}

public class Box: Shape
{
    public override void Paint(Graphics g, Rectangle r) {
        g.DrawRect(r);
    }
}

Shapeクラス自体を描画できる幾何学的な図形オブジェクトの抽象概念を定義します。the Shape class defines the abstract notion of a geometrical shape object that can paint itself. Paint意味のある既定の実装がないため、抽象メソッドです。The Paint method is abstract because there is no meaningful default implementation. EllipseBoxクラスは具象Shape実装します。The Ellipse and Box classes are concrete Shape implementations. オーバーライドする必要がこれらのクラスは、非抽象であるため、Paintメソッドと、実際の実装を提供します。Because these classes are non-abstract, they are required to override the Paint method and provide an actual implementation.

コンパイル時エラーには、 base_access (Base アクセス) を抽象メソッドを参照します。It is a compile-time error for a base_access (Base access) to reference an abstract method. In the example

abstract class A
{
    public abstract void F();
}

class B: A
{
    public override void F() {
        base.F();                        // Error, base.F is abstract
    }
}

コンパイル時エラーが報告された、base.F()呼び出し抽象メソッドを参照しているためです。a compile-time error is reported for the base.F() invocation because it references an abstract method.

抽象メソッドの宣言は、仮想メソッドをオーバーライド許可されています。An abstract method declaration is permitted to override a virtual method. これにより、派生クラスでメソッドの再実装を強制する抽象クラスとメソッドの元の実装を使用できなくなります。This allows an abstract class to force re-implementation of the method in derived classes, and makes the original implementation of the method unavailable. In the example

using System;

class A
{
    public virtual void F() {
        Console.WriteLine("A.F");
    }
}

abstract class B: A
{
    public abstract override void F();
}

class C: B
{
    public override void F() {
        Console.WriteLine("C.F");
    }
}

クラスA仮想メソッド、クラスを宣言B抽象メソッドとクラスを使用してこのメソッドをオーバーライドC独自の実装を提供する抽象メソッドをオーバーライドします。class A declares a virtual method, class B overrides this method with an abstract method, and class C overrides the abstract method to provide its own implementation.

外部メソッドExternal methods

メソッドの宣言が含まれています、extern修飾子、メソッドがあると言うこと、外部メソッドします。When a method declaration includes an extern modifier, that method is said to be an external method. 外部メソッドは、通常 c# 以外の言語を使用して外部で実装されます。External methods are implemented externally, typically using a language other than C#. 外部メソッドの宣言は、実際の実装を提供するため、 method_bodyの外部メソッドをセミコロンの構成だけです。Because an external method declaration provides no actual implementation, the method_body of an external method simply consists of a semicolon. 外部メソッドのジェネリックできない可能性があります。An external method may not be generic.

extern修飾子が組み合わせてで通常使用される、DllImport属性 (と Win32 の COM コンポーネントとの相互運用)、外部メソッドを Dll (ダイナミック リンク ライブラリ) によって実装することができます。The extern modifier is typically used in conjunction with a DllImport attribute (Interoperation with COM and Win32 components), allowing external methods to be implemented by DLLs (Dynamic Link Libraries). 実行環境では、外部メソッドの実装を提供できる、他のメカニズムをサポートできます。The execution environment may support other mechanisms whereby implementations of external methods can be provided.

外部メソッドが含まれる場合、DllImport属性、メソッドの宣言を含める必要がありますも、static修飾子。When an external method includes a DllImport attribute, the method declaration must also include a static modifier. この例の使用、extern修飾子とDllImport属性。This example demonstrates the use of the extern modifier and the DllImport attribute:

using System.Text;
using System.Security.Permissions;
using System.Runtime.InteropServices;

class Path
{
    [DllImport("kernel32", SetLastError=true)]
    static extern bool CreateDirectory(string name, SecurityAttribute sa);

    [DllImport("kernel32", SetLastError=true)]
    static extern bool RemoveDirectory(string name);

    [DllImport("kernel32", SetLastError=true)]
    static extern int GetCurrentDirectory(int bufSize, StringBuilder buf);

    [DllImport("kernel32", SetLastError=true)]
    static extern bool SetCurrentDirectory(string name);
}

部分メソッド (まとめ)Partial methods (recap)

メソッドの宣言が含まれています、partial修飾子、メソッドがあると言うこと、部分メソッドします。When a method declaration includes a partial modifier, that method is said to be a partial method. 部分メソッドは、部分型のメンバーとしてのみ宣言できます (部分型)、およびいくつかの制限を受けます。Partial methods can only be declared as members of partial types (Partial types), and are subject to a number of restrictions. 部分メソッドはさらに「部分メソッドします。Partial methods are further described in Partial methods.

拡張メソッドExtension methods

メソッドの最初のパラメーターが含まれる場合、this修飾子、メソッドがあると言うこと、拡張メソッドします。When the first parameter of a method includes the this modifier, that method is said to be an extension method. 拡張メソッドは、非ジェネリック、入れ子になった非静的クラスでのみ宣言できます。Extension methods can only be declared in non-generic, non-nested static classes. 拡張メソッドの最初のパラメーターを持たない修飾子以外thisパラメーターの型がポインター型にすることはできません。The first parameter of an extension method can have no modifiers other than this, and the parameter type cannot be a pointer type.

2 つの拡張メソッドを宣言する静的クラスの例を次に示します。The following is an example of a static class that declares two extension methods:

public static class Extensions
{
    public static int ToInt32(this string s) {
        return Int32.Parse(s);
    }

    public static T[] Slice<T>(this T[] source, int index, int count) {
        if (index < 0 || count < 0 || source.Length - index < count)
            throw new ArgumentException();
        T[] result = new T[count];
        Array.Copy(source, index, result, 0, count);
        return result;
    }
}

拡張メソッドは、通常の静的メソッドです。An extension method is a regular static method. さらに、その外側の静的クラスは、スコープ内では、拡張メソッド呼び出すことができますのインスタンス メソッドの呼び出し構文を使用して (拡張メソッド呼び出し)、最初の引数として受信者式を使用します。In addition, where its enclosing static class is in scope, an extension method can be invoked using instance method invocation syntax (Extension method invocations), using the receiver expression as the first argument.

次のプログラムでは、上で宣言された拡張メソッドを使用します。The following program uses the extension methods declared above:

static class Program
{
    static void Main() {
        string[] strings = { "1", "22", "333", "4444" };
        foreach (string s in strings.Slice(1, 2)) {
            Console.WriteLine(s.ToInt32());
        }
    }
}

Sliceメソッドは、の使用、 string[]、およびToInt32メソッドで使用string拡張メソッドとして宣言されているため、します。The Slice method is available on the string[], and the ToInt32 method is available on string, because they have been declared as extension methods. プログラムの意味では、次を使用して、通常の静的メソッドの呼び出しと同じです。The meaning of the program is the same as the following, using ordinary static method calls:

static class Program
{
    static void Main() {
        string[] strings = { "1", "22", "333", "4444" };
        foreach (string s in Extensions.Slice(strings, 1, 2)) {
            Console.WriteLine(Extensions.ToInt32(s));
        }
    }
}

メソッドの本体Method body

Method_bodyブロック本体を式の本体またはセミコロンのいずれかのメソッドの宣言がで構成されます。The method_body of a method declaration consists of either a block body, an expression body or a semicolon.

型の結果メソッドがvoid戻り値の型がある場合void、メソッドは非同期と戻り値の型である場合またはSystem.Threading.Tasks.Taskします。The result type of a method is void if the return type is void, or if the method is async and the return type is System.Threading.Tasks.Task. 戻り値の型、および非同期メソッドの戻り値の型の結果型では、非同期メソッドの結果型は、それ以外の場合、System.Threading.Tasks.Task<T>Tします。Otherwise, the result type of a non-async method is its return type, and the result type of an async method with return type System.Threading.Tasks.Task<T> is T.

メソッドにある場合、void結果の種類とブロックの本体、returnステートメント (return ステートメント) ブロックが式を指定することできません。When a method has a void result type and a block body, return statements (The return statement) in the block are not permitted to specify an expression. Void メソッドのブロックの実行が正常に完了するかどうか (つまり、メソッド本体の末尾からのフロー制御) メソッドが、現在の呼び出し元に単に返します。If execution of the block of a void method completes normally (that is, control flows off the end of the method body), that method simply returns to its current caller.

メソッドにある場合、void結果および式、式の本文E必要があります、 statement_expression、本文がフォームのブロックの本体とまったく同じ{ E; }When a method has a void result and an expression body, the expression E must be a statement_expression, and the body is exactly equivalent to a block body of the form { E; }.

メソッドが void 以外の結果の型を持つ、ブロック、本体の各returnブロックのステートメントでは、結果の型に暗黙的に変換される式を指定する必要があります。When a method has a non-void result type and a block body, each return statement in the block must specify an expression that is implicitly convertible to the result type. 値を返すメソッドのブロックの本体のエンドポイントが到達可能な場合があります。The endpoint of a block body of a value-returning method must not be reachable. つまり、ブロックの本体で値を返すメソッドでは、コントロールは許可されていません、メソッド本体の末尾に到達します。In other words, in a value-returning method with a block body, control is not permitted to flow off the end of the method body.

メソッドが void 以外の結果型は、式の本体と式は、結果の型に暗黙的に変換可能である必要があります、本文がフォームのブロックの本体と同じ{ return E; }します。When a method has a non-void result type and an expression body, the expression must be implicitly convertible to the result type, and the body is exactly equivalent to a block body of the form { return E; }.

In the example

class A
{
    public int F() {}            // Error, return value required

    public int G() {
        return 1;
    }

    public int H(bool b) {
        if (b) {
            return 1;
        }
        else {
            return 0;
        }
    }

    public int I(bool b) => b ? 1 : 0;
}

値を返すFメソッドは、制御は、メソッド本体の最後にフローできるため、コンパイル時エラーが発生結果します。the value-returning F method results in a compile-time error because control can flow off the end of the method body. GHメソッドは、すべての実行可能なパスが戻り値を指定する、return ステートメントで終了するので、正しい。The G and H methods are correct because all possible execution paths end in a return statement that specifies a return value. Iの本体は等価ですが 1 つの戻りステートメントだけでステートメント ブロックされるため、メソッドです。The I method is correct, because its body is equivalent to a statement block with just a single return statement in it.

メソッドのオーバーロードMethod overloading

メソッドのオーバー ロード解決規則が記載されて型推論します。The method overload resolution rules are described in Type inference.

プロパティProperties

Aプロパティオブジェクトまたはクラスの特性へのアクセスを提供するメンバーします。A property is a member that provides access to a characteristic of an object or a class. プロパティの例では、顧客の名前、ウィンドウのキャプションのフォントのサイズの文字列の長さを含めるし、具合です。Examples of properties include the length of a string, the size of a font, the caption of a window, the name of a customer, and so on. プロパティは、フィールドの自然な拡張機能、両方を関連する型を持つメンバーを指定し、フィールドとプロパティにアクセスするための構文は同じです。Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. ただし、フィールドとは異なり、プロパティは格納場所を表しません。However, unlike fields, properties do not denote storage locations. その代わりに、プロパティには、値の読み取りまたは書き込みの際に実行されるステートメントを指定する "アクセサー" があります。Instead, properties have accessors that specify the statements to be executed when their values are read or written. プロパティはオブジェクトの属性の書き込みと読み取りにアクションを関連付けるためのメカニズムを提供するためさらに、それらを計算するには、このような属性を許可します。Properties thus provide a mechanism for associating actions with the reading and writing of an object's attributes; furthermore, they permit such attributes to be computed.

プロパティを使用して宣言property_declaration: %sProperties are declared using property_declarations:

property_declaration
    : attributes? property_modifier* type member_name property_body
    ;

property_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | property_modifier_unsafe
    ;

property_body
    : '{' accessor_declarations '}' property_initializer?
    | '=>' expression ';'
    ;

property_initializer
    : '=' variable_initializer ';'
    ;

A property_declarationのセットを含めることができます属性(属性) と有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)、 new (new 修飾子)、 static (静的およびインスタンス メソッド)、 virtual (仮想メソッド)、 override (メソッドをオーバーライド)、 sealed (メソッドをシール)、 abstract (抽象メソッド)、およびextern (外部メソッド) 修飾子。A property_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), static (Static and instance methods), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

プロパティ宣言では、メソッドの宣言と同じ規則 (メソッド) 修飾子の組み合わせが無効です。Property declarations are subject to the same rules as method declarations (Methods) with regard to valid combinations of modifiers.

プロパティの宣言は、宣言によって導入されるプロパティの型を指定します、 member_nameプロパティの名前を指定します。The type of a property declaration specifies the type of the property introduced by the declaration, and the member_name specifies the name of the property. プロパティが、明示的なインターフェイス メンバーの実装でない限り、 member_nameは単に、識別子します。Unless the property is an explicit interface member implementation, the member_name is simply an identifier. 明示的なインターフェイス メンバーの実装 (明示的なインターフェイス メンバーの実装)、 member_nameから成る、 interface_type後に、"."および識別子します。For an explicit interface member implementation (Explicit interface member implementations), the member_name consists of an interface_type followed by a "." and an identifier.

プロパティは少なくともプロパティ自体と同程度にアクセスできる必要があります (アクセシビリティ制約)。The type of a property must be at least as accessible as the property itself (Accessibility constraints).

A property_bodyので構成するか、アクセサー本体または式本体します。A property_body may either consist of an accessor body or an expression body. アクセサーの本体でaccessor_declarations、これで囲む必要があります"{「と」}"トークンは、アクセサーを宣言する (アクセサー) プロパティの。In an accessor body, accessor_declarations, which must be enclosed in "{" and "}" tokens, declare the accessors (Accessors) of the property. アクセサーは、読み取りと書き込みのプロパティに関連付けられている実行可能ステートメントを指定します。The accessors specify the executable statements associated with reading and writing the property.

構成される式の本体=>続けて、Eセミコロンはステートメント本体内でまったく同じですが、 { get { return E; } }、ことができますのみため、get アクセス操作子のみを指定するにはプロパティは、get アクセス操作子の結果は 1 つの式で指定した場合。An expression body consisting of => followed by an expression E and a semicolon is exactly equivalent to the statement body { get { return E; } }, and can therefore only be used to specify getter-only properties where the result of the getter is given by a single expression.

A property_initializerを自動的に実装されたプロパティ用にのみ与えられます (自動実装プロパティ)、し、このような基になるフィールドの初期化プロパティで指定された値、します。A property_initializer may only be given for an automatically implemented property (Automatically implemented properties), and causes the initialization of the underlying field of such properties with the value given by the expression.

プロパティにアクセスするための構文と同じではフィールドが、プロパティは変数としては分類されません。Even though the syntax for accessing a property is the same as that for a field, a property is not classified as a variable. したがって、としてプロパティを渡すことはできません、refまたはout引数。Thus, it is not possible to pass a property as a ref or out argument.

プロパティの宣言が含まれています、extern修飾子は、このプロパティがあると、外部プロパティWhen a property declaration includes an extern modifier, the property is said to be an external property. 外部プロパティの宣言は、それぞれの実際の実装を提供するため、 accessor_declarationsをセミコロンで構成されます。Because an external property declaration provides no actual implementation, each of its accessor_declarations consists of a semicolon.

静的およびインスタンスのプロパティStatic and instance properties

プロパティの宣言が含まれています、static修飾子は、このプロパティがあると、静的プロパティWhen a property declaration includes a static modifier, the property is said to be a static property. ない場合static修飾子が存在する、このプロパティにすると、インスタンス プロパティします。When no static modifier is present, the property is said to be an instance property.

静的プロパティは、特定のインスタンスに関連付けられていないを参照すると、コンパイル時エラーthis静的プロパティのアクセサーでします。A static property is not associated with a specific instance, and it is a compile-time error to refer to this in the accessors of a static property.

インスタンス プロパティは、クラスのインスタンスに関連付けられていると、そのインスタンスとしてアクセスできますthis(このアクセス) でそのプロパティのアクセサー。An instance property is associated with a given instance of a class, and that instance can be accessed as this (This access) in the accessors of that property.

プロパティが参照されている場合、 member_access (メンバー アクセス) フォームのE.M場合は、M静的なプロパティは、 E を含む型を表す必要がありますM、場合Mインスタンス プロパティは、電子メールに含まれる型のインスタンスを表す必要がありますMします。When a property is referenced in a member_access (Member access) of the form E.M, if M is a static property, E must denote a type containing M, and if M is an instance property, E must denote an instance of a type containing M.

静的な違いは、インスタンス メンバーの説明とでさらに静的メンバーとインスタンス メンバーThe differences between static and instance members are discussed further in Static and instance members.

アクセサーAccessors

Accessor_declarationsプロパティの読み取りと書き込みのプロパティに関連付けられている実行可能なステートメントを指定します。The accessor_declarations of a property specify the executable statements associated with reading and writing that property.

accessor_declarations
    : get_accessor_declaration set_accessor_declaration?
    | set_accessor_declaration get_accessor_declaration?
    ;

get_accessor_declaration
    : attributes? accessor_modifier? 'get' accessor_body
    ;

set_accessor_declaration
    : attributes? accessor_modifier? 'set' accessor_body
    ;

accessor_modifier
    : 'protected'
    | 'internal'
    | 'private'
    | 'protected' 'internal'
    | 'internal' 'protected'
    ;

accessor_body
    : block
    | ';'
    ;

アクセサーの宣言から成る、 get_accessor_declarationset_accessor_declaration、またはその両方です。The accessor declarations consist of a get_accessor_declaration, a set_accessor_declaration, or both. 各アクセサーの宣言は、トークンのgetまたはset続く省略可能なaccessor_modifieraccessor_bodyします。Each accessor declaration consists of the token get or set followed by an optional accessor_modifier and an accessor_body.

使用accessor_modifiers は、次の制限によって管理されます。The use of accessor_modifiers is governed by the following restrictions:

  • Accessor_modifierインターフェイスまたは明示的なインターフェイス メンバーの実装で使用できません。An accessor_modifier may not be used in an interface or in an explicit interface member implementation.
  • プロパティまたはインデクサーを持たないoverride修飾子、 accessor_modifierプロパティまたはインデクサーの両方がある場合にのみ許可されて、getsetアクセサー、およびうちの 1 つでのみ許可し、アクセサー。For a property or indexer that has no override modifier, an accessor_modifier is permitted only if the property or indexer has both a get and set accessor, and then is permitted only on one of those accessors.
  • プロパティまたはインデクサーを含む、override修飾子をアクセサーが一致する必要があります、 accessor_modifierいずれかオーバーライドされるアクセサーの場合は、します。For a property or indexer that includes an override modifier, an accessor must match the accessor_modifier, if any, of the accessor being overridden.
  • Accessor_modifierプロパティまたはインデクサー自体の宣言されたアクセシビリティよりも厳密に制限は、アクセシビリティを宣言する必要があります。The accessor_modifier must declare an accessibility that is strictly more restrictive than the declared accessibility of the property or indexer itself. 正確には。To be precise:
    • プロパティまたはインデクサーの宣言されたアクセシビリティを持つかどうかpublicaccessor_modifierにある場合もprotected internalinternalprotected、またはprivateします。If the property or indexer has a declared accessibility of public, the accessor_modifier may be either protected internal, internal, protected, or private.
    • プロパティまたはインデクサーの宣言されたアクセシビリティを持つかどうかprotected internalaccessor_modifierにある場合もinternalprotected、またはprivateします。If the property or indexer has a declared accessibility of protected internal, the accessor_modifier may be either internal, protected, or private.
    • プロパティまたはインデクサーの宣言されたアクセシビリティを持つかどうかinternalまたはprotectedaccessor_modifierありますprivateします。If the property or indexer has a declared accessibility of internal or protected, the accessor_modifier must be private.
    • プロパティまたはインデクサーの宣言されたアクセシビリティを持つかどうかprivateaccessor_modifier使用可能性があります。If the property or indexer has a declared accessibility of private, no accessor_modifier may be used.

abstractexternプロパティ、 accessor_body指定された各アクセサーは、セミコロンだけです。For abstract and extern properties, the accessor_body for each accessor specified is simply a semicolon. 各非 abstract、extern 以外のプロパティがありますaccessor_bodyセミコロンをする場合は、プロパティが自動的に実装(自動実装プロパティ).A non-abstract, non-extern property may have each accessor_body be a semicolon, in which case it is an automatically implemented property (Automatically implemented properties). 自動的に実装されたプロパティを get アクセサーが必要です。An automatically implemented property must have at least a get accessor. その他の非 abstract、extern 以外、任意のプロパティのアクセサーに、 accessor_bodyは、ブロック対応するアクセサーが呼び出されたときに実行されるステートメントを指定します。For the accessors of any other non-abstract, non-extern property, the accessor_body is a block which specifies the statements to be executed when the corresponding accessor is invoked.

Agetアクセサーはプロパティの型の値を返すパラメーターなしのメソッドに相当します。A get accessor corresponds to a parameterless method with a return value of the property type. 代入のターゲット プロパティが式で参照されている場合を除き、getプロパティの値を計算する、プロパティのアクセサーが呼び出されます (式の値)。Except as the target of an assignment, when a property is referenced in an expression, the get accessor of the property is invoked to compute the value of the property (Values of expressions). 本文をgetアクセサーは値を返すの規則に従う必要がありますで説明したメソッドメソッド本体します。The body of a get accessor must conform to the rules for value-returning methods described in Method body. 具体的には、すべてreturnステートメントの本体で、getアクセサーはプロパティの型に暗黙的に変換される式を指定する必要があります。In particular, all return statements in the body of a get accessor must specify an expression that is implicitly convertible to the property type. さらのエンドポイントをgetアクセサーに到達できないする必要があります。Furthermore, the endpoint of a get accessor must not be reachable.

Asetアクセサーはプロパティの型の 1 つの値を持つパラメーターを持つメソッドに相当し、void型を返します。A set accessor corresponds to a method with a single value parameter of the property type and a void return type. 暗黙のパラメーターをsetアクセサーの名前は常にvalueします。The implicit parameter of a set accessor is always named value. プロパティが割り当ての対象として参照されている場合 (代入演算子)、またはのオペランドとして++または--(置インクリメント演算子と前置デクリメント演算子前置インクリメントとデクリメント演算子)、set引数にアクセサーが呼び出されます (値が代入の右側にあるかのオペランドの++または--演算子) を新しい値を提供します (単純な代入)。When a property is referenced as the target of an assignment (Assignment operators), or as the operand of ++ or -- (Postfix increment and decrement operators, Prefix increment and decrement operators), the set accessor is invoked with an argument (whose value is that of the right-hand side of the assignment or the operand of the ++ or -- operator) that provides the new value (Simple assignment). 本文をsetアクセサーがの規則に従う必要がありますvoidで説明したメソッドメソッド本体します。The body of a set accessor must conform to the rules for void methods described in Method body. 具体的には、return内のステートメント、set式を指定するアクセサーの本体は許可されていません。In particular, return statements in the set accessor body are not permitted to specify an expression. setアクセサーがという名前のパラメーターを暗黙的にvalueは、ローカル変数または定数宣言でのコンパイル時エラーです、set名前がアクセサー。Since a set accessor implicitly has a parameter named value, it is a compile-time error for a local variable or constant declaration in a set accessor to have that name.

有無に基づいて、getsetアクセサー、プロパティは次のように分類されます。Based on the presence or absence of the get and set accessors, a property is classified as follows:

  • 両方が含まれるプロパティをgetアクセサーとsetアクセサーはモード、読み取り/書き込みプロパティ。A property that includes both a get accessor and a set accessor is said to be a read-write property.
  • のみを持つプロパティをgetアクセサーはモード、読み取り専用プロパティ。A property that has only a get accessor is said to be a read-only property. 割り当ての対象となる読み取り専用プロパティのコンパイル時エラーになります。It is a compile-time error for a read-only property to be the target of an assignment.
  • のみを持つプロパティをsetアクセサーはモード、書き込み専用プロパティ。A property that has only a set accessor is said to be a write-only property. ただし、代入式のターゲットとして式の中で、書き込み専用プロパティを参照すると、コンパイル時エラーになります。Except as the target of an assignment, it is a compile-time error to reference a write-only property in an expression.

In the example

public class Button: Control
{
    private string caption;

    public string Caption {
        get {
            return caption;
        }
        set {
            if (caption != value) {
                caption = value;
                Repaint();
            }
        }
    }

    public override void Paint(Graphics g, Rectangle r) {
        // Painting code goes here
    }
}

Buttonコントロール宣言パブリックCaptionプロパティ。the Button control declares a public Caption property. getのアクセサー、Captionプロパティがプライベートに格納された文字列を返しますcaptionフィールド。The get accessor of the Caption property returns the string stored in the private caption field. setアクセサーは、新しい値を格納する場合は、新しい値が現在の値と異なる場合にチェックし、コントロールを再描画します。The set accessor checks if the new value is different from the current value, and if so, it stores the new value and repaints the control. 多くの場合、プロパティには、上記のパターンに従います。getアクセサーはプライベート フィールドに格納されている値だけを返します、setアクセサーは、そのプライベート フィールドを変更し、オブジェクトの状態を完全に更新するために必要な追加の操作を実行します。Properties often follow the pattern shown above: The get accessor simply returns a value stored in a private field, and the set accessor modifies that private field and then performs any additional actions required to fully update the state of the object.

指定された、Button上記のクラス、例を次の使用、Captionプロパティ。Given the Button class above, the following is an example of use of the Caption property:

Button okButton = new Button();
okButton.Caption = "OK";            // Invokes set accessor
string s = okButton.Caption;        // Invokes get accessor

ここでは、setアクセサーがプロパティの値を割り当てることによって呼び出されると、getアクセサーは、式でプロパティを参照することによって呼び出されます。Here, the set accessor is invoked by assigning a value to the property, and the get accessor is invoked by referencing the property in an expression.

getsetプロパティのアクセサーが個別のメンバーでないし、プロパティのアクセサーを個別に宣言することはできません。The get and set accessors of a property are not distinct members, and it is not possible to declare the accessors of a property separately. そのため、読み取り/書き込みプロパティの 2 つのアクセサーが異なるアクセシビリティを持つことはできません。As such, it is not possible for the two accessors of a read-write property to have different accessibility. 例では、The example

class A
{
    private string name;

    public string Name {                // Error, duplicate member name
        get { return name; }
    }

    public string Name {                // Error, duplicate member name
        set { name = value; }
    }
}

1 つの読み取り/書き込みプロパティを宣言していません。does not declare a single read-write property. 読み取り専用のいずれか、同じ名前の 2 つのプロパティを宣言ではなく、書き込み専用の 1 つ。Rather, it declares two properties with the same name, one read-only and one write-only. 同じクラスで宣言されている 2 つのメンバーは、同じ名前を持つことはできません、ため、例ではコンパイル時エラーが発生、します。Since two members declared in the same class cannot have the same name, the example causes a compile-time error to occur.

派生クラスでは、継承されたプロパティと同じ名前でプロパティを宣言して、派生プロパティの読み取りと書き込みの両方に関して、継承されたプロパティを非表示にします。When a derived class declares a property by the same name as an inherited property, the derived property hides the inherited property with respect to both reading and writing. In the example

class A
{
    public int P {
        set {...}
    }
}

class B: A
{
    new public int P {
        get {...}
    }
}

PプロパティBを非表示に、PプロパティAの読み取りと書き込みの両方に対して。the P property in B hides the P property in A with respect to both reading and writing. そのため、ステートメントでThus, in the statements

B b = new B();
b.P = 1;          // Error, B.P is read-only
((A)b).P = 1;     // Ok, reference to A.P

割り当てをb.P以降、読み取り専用、報告されることをコンパイル時エラーが発生PプロパティB書き込み専用の表示と非PプロパティAします。the assignment to b.P causes a compile-time error to be reported, since the read-only P property in B hides the write-only P property in A. ただし、キャストを隠しへのアクセスに使用できることPプロパティ。Note, however, that a cast can be used to access the hidden P property.

パブリックのフィールドとは異なりは、プロパティは、オブジェクトの内部状態とそのパブリック インターフェイスとの間の分離を提供します。Unlike public fields, properties provide a separation between an object's internal state and its public interface. この例を検討してください。Consider the example:

class Label
{
    private int x, y;
    private string caption;

    public Label(int x, int y, string caption) {
        this.x = x;
        this.y = y;
        this.caption = caption;
    }

    public int X {
        get { return x; }
    }

    public int Y {
        get { return y; }
    }

    public Point Location {
        get { return new Point(x, y); }
    }

    public string Caption {
        get { return caption; }
    }
}

ここでは、Labelクラスを使用して 2 つintフィールド、xy、その場所を格納します。Here, the Label class uses two int fields, x and y, to store its location. パブリックには、場所は両方として公開されている、XYプロパティとして、Location型のプロパティPointThe location is publicly exposed both as an X and a Y property and as a Location property of type Point. 将来のバージョンの場合、Labelと場所を格納する方が便利になります、Point内部的には、変更できるクラスのパブリック インターフェイスの影響を与えずに。If, in a future version of Label, it becomes more convenient to store the location as a Point internally, the change can be made without affecting the public interface of the class:

class Label
{
    private Point location;
    private string caption;

    public Label(int x, int y, string caption) {
        this.location = new Point(x, y);
        this.caption = caption;
    }

    public int X {
        get { return location.x; }
    }

    public int Y {
        get { return location.y; }
    }

    public Point Location {
        get { return location; }
    }

    public string Caption {
        get { return caption; }
    }
}

xyされて代わりにpublic readonlyフィールド、それはされているを変更すること、Labelクラス。Had x and y instead been public readonly fields, it would have been impossible to make such a change to the Label class.

プロパティから状態を公開することは必ずしもフィールドを直接公開するよりも効率が落ちるではありません。Exposing state through properties is not necessarily any less efficient than exposing fields directly. 具体的には、プロパティは、非仮想少量のコードのみを含む、ときに実行環境がアクセサーへの呼び出し、アクセサーの実際のコードに置き換えます。In particular, when a property is non-virtual and contains only a small amount of code, the execution environment may replace calls to accessors with the actual code of the accessors. このプロセスと呼びますインライン展開、およびフィールドへのアクセス、ほど効率的プロパティへのアクセスは、まだプロパティの柔軟性の向上が保持されます。This process is known as inlining, and it makes property access as efficient as field access, yet preserves the increased flexibility of properties.

以降の呼び出しをgetアクセサーは概念的には、フィールドの値を読み取るのと同じですが、プログラミング スタイルは不適切と見なされますgetアクセサーを観測可能な副作用があります。Since invoking a get accessor is conceptually equivalent to reading the value of a field, it is considered bad programming style for get accessors to have observable side-effects. In the example

class Counter
{
    private int next;

    public int Next {
        get { return next++; }
    }
}

値、Nextプロパティは、プロパティにアクセスした回数によって異なります。the value of the Next property depends on the number of times the property has previously been accessed. したがって、監視可能な側効果を生成するプロパティにアクセスする、プロパティを代わりに、メソッドとして実装する必要があります。Thus, accessing the property produces an observable side-effect, and the property should be implemented as a method instead.

「副作用」の規則getアクセサーは、ことを意味しないgetを単にフィールドに格納されている値を返すアクセサーを記述する必要があります。The "no side-effects" convention for get accessors doesn't mean that get accessors should always be written to simply return values stored in fields. 実際、getアクセサーは多くの場合、複数のフィールドへのアクセスやメソッドの呼び出しによってプロパティの値を計算します。Indeed, get accessors often compute the value of a property by accessing multiple fields or invoking methods. ただし、適切にデザインされたgetアクセサーは、オブジェクトの状態の監視可能な変更を引き起こす操作を行いません。However, a properly designed get accessor performs no actions that cause observable changes in the state of the object.

最初に参照される時点まで、リソースの初期化を遅延プロパティを使用できます。Properties can be used to delay initialization of a resource until the moment it is first referenced. 例:For example:

using System.IO;

public class Console
{
    private static TextReader reader;
    private static TextWriter writer;
    private static TextWriter error;

    public static TextReader In {
        get {
            if (reader == null) {
                reader = new StreamReader(Console.OpenStandardInput());
            }
            return reader;
        }
    }

    public static TextWriter Out {
        get {
            if (writer == null) {
                writer = new StreamWriter(Console.OpenStandardOutput());
            }
            return writer;
        }
    }

    public static TextWriter Error {
        get {
            if (error == null) {
                error = new StreamWriter(Console.OpenStandardError());
            }
            return error;
        }
    }
}

Consoleクラスには、3 つのプロパティが含まれています。 InOut、およびError、標準入力、出力、およびデバイスのエラーをそれぞれ表すです。The Console class contains three properties, In, Out, and Error, that represent the standard input, output, and error devices, respectively. これらのメンバーのプロパティとして公開することで、Consoleクラスは実際に使用されるまで初期化を遅らせることができます。By exposing these members as properties, the Console class can delay their initialization until they are actually used. たとえば、最初に参照するときとき、Outに示すように、プロパティFor example, upon first referencing the Out property, as in

Console.Out.WriteLine("hello, world");

基になるTextWriter出力デバイスを作成します。the underlying TextWriter for the output device is created. アプリケーションへの参照がない場合は、InErrorそれらのデバイス プロパティ、そのオブジェクトが作成されます。But if the application makes no reference to the In and Error properties, then no objects are created for those devices.

自動実装プロパティAutomatically implemented properties

自動的に実装されたプロパティ (または自動プロパティ省略形)、セミコロン専用のアクセサー本体を持つ非抽象 extern 以外のプロパティです。An automatically implemented property (or auto-property for short), is a non-abstract non-extern property with semicolon-only accessor bodies. 自動プロパティを使用して、get アクセサーがあります、set アクセサーを持つことができます必要に応じて。Auto-properties must have a get accessor and can optionally have a set accessor.

プロパティを指定するには、自動的に実装されたプロパティとして、非表示のバッキング フィールドが自動的には、プロパティの使用可能なとアクセサーが読み取りし、そのバッキング フィールドへの書き込みのために実装されます。When a property is specified as an automatically implemented property, a hidden backing field is automatically available for the property, and the accessors are implemented to read from and write to that backing field. バッキング フィールドと見なされます自動プロパティには、set アクセサーがなければ、 readonly (読み取り専用フィールド)。If the auto-property has no set accessor, the backing field is considered readonly (Readonly fields). 同じように、readonlyフィールドを getter 専用自動プロパティ割り当てることもできますを外側のクラスのコンス トラクターの本体でします。Just like a readonly field, a getter-only auto-property can also be assigned to in the body of a constructor of the enclosing class. このような割り当ては、プロパティの読み取り専用のバッキング フィールドに直接割り当てられます。Such an assignment assigns directly to the readonly backing field of the property.

自動プロパティことができます、 property_initializer、として、バッキング フィールドに直接適用、 variable_initializer (変数初期化子).An auto-property may optionally have a property_initializer, which is applied directly to the backing field as a variable_initializer (Variable initializers).

次のような例です。The following example:

public class Point {
    public int X { get; set; } = 0;
    public int Y { get; set; } = 0;
}

次の宣言と同等です。is equivalent to the following declaration:

public class Point {
    private int __x = 0;
    private int __y = 0;
    public int X { get { return __x; } set { __x = value; } }
    public int Y { get { return __y; } set { __y = value; } }
}

次のような例です。The following example:

public class ReadOnlyPoint
{
    public int X { get; }
    public int Y { get; }
    public ReadOnlyPoint(int x, int y) { X = x; Y = y; }
}

次の宣言と同等です。is equivalent to the following declaration:

public class ReadOnlyPoint
{
    private readonly int __x;
    private readonly int __y;
    public int X { get { return __x; } }
    public int Y { get { return __y; } }
    public ReadOnlyPoint(int x, int y) { __x = x; __y = y; }
}

コンス トラクター内で発生したため、読み取り専用フィールドへの割り当てが、有効なことに注意してください。Notice that the assignments to the readonly field are legal, because they occur within the constructor.

ユーザー補助Accessibility

アクセサーがある場合、 accessor_modifier、アクセシビリティ ドメイン (アクセシビリティ ドメイン) は、アクセサーの決まりますの宣言されたアクセシビリティを使用して、 accessor_modifier.If an accessor has an accessor_modifier, the accessibility domain (Accessibility domains) of the accessor is determined using the declared accessibility of the accessor_modifier. アクセサーがない場合、 accessor_modifierアクセサーのアクセシビリティ ドメインは、プロパティまたはインデクサーの宣言されたアクセシビリティから決定されます。If an accessor does not have an accessor_modifier, the accessibility domain of the accessor is determined from the declared accessibility of the property or indexer.

有無、 accessor_modifierメンバー検索には影響せず (演算子) オーバー ロードの解決または (オーバー ロードの解決)。The presence of an accessor_modifier never affects member lookup (Operators) or overload resolution (Overload resolution). プロパティまたはインデクサーに修飾子のプロパティまたはインデクサーは、バインドのアクセス権のコンテキストに関係なく常に判別します。The modifiers on the property or indexer always determine which property or indexer is bound to, regardless of the context of the access.

特定のプロパティまたはインデクサーが選択されていると、その使用法が有効であるかを判断する関連する特定のアクセサーのアクセシビリティ ドメインが使用されます。Once a particular property or indexer has been selected, the accessibility domains of the specific accessors involved are used to determine if that usage is valid:

  • 値として使用する場合 (式の値)、getアクセサーが存在し、アクセスできるようにする必要があります。If the usage is as a value (Values of expressions), the get accessor must exist and be accessible.
  • 単純な代入のターゲットとして使用する場合 (単純な代入)、setアクセサーが存在し、アクセスできるようにする必要があります。If the usage is as the target of a simple assignment (Simple assignment), the set accessor must exist and be accessible.
  • 複合代入のターゲットとして使用するかどうかは (複合代入)、またはの対象として、++または--演算子 (関数メンバー.9、 Invocation 式) の両方をgetアクセサーとsetアクセサーが存在し、アクセスできるようにする必要があります。If the usage is as the target of compound assignment (Compound assignment), or as the target of the ++ or -- operators (Function members.9, Invocation expressions), both the get accessors and the set accessor must exist and be accessible.

次の例では、プロパティでA.Textプロパティによって隠されているB.Textのみのコンテキストであっても、setアクセサーが呼び出されます。In the following example, the property A.Text is hidden by the property B.Text, even in contexts where only the set accessor is called. プロパティとは異なり、B.CountがクラスにアクセスできないMため、アクセス可能なプロパティA.Count代わりに使用されます。In contrast, the property B.Count is not accessible to class M, so the accessible property A.Count is used instead.

class A
{
    public string Text {
        get { return "hello"; }
        set { }
    }

    public int Count {
        get { return 5; }
        set { }
    }
}

class B: A
{
    private string text = "goodbye"; 
    private int count = 0;

    new public string Text {
        get { return text; }
        protected set { text = value; }
    }

    new protected int Count { 
        get { return count; }
        set { count = value; }
    }
}

class M
{
    static void Main() {
        B b = new B();
        b.Count = 12;             // Calls A.Count set accessor
        int i = b.Count;          // Calls A.Count get accessor
        b.Text = "howdy";         // Error, B.Text set accessor not accessible
        string s = b.Text;        // Calls B.Text get accessor
    }
}

インターフェイスを実装するために使用されるアクセサーがない可能性があります、 accessor_modifierします。An accessor that is used to implement an interface may not have an accessor_modifier. 他のアクセサーを宣言することも 1 つのアクセサーを使用するインターフェイスを実装すると、専用の場合、 accessor_modifier:If only one accessor is used to implement an interface, the other accessor may be declared with an accessor_modifier:

public interface I
{
    string Prop { get; }
}

public class C: I
{
    public Prop {
        get { return "April"; }       // Must not have a modifier here
        internal set {...}            // Ok, because I.Prop has no set accessor
    }
}

封印されて、仮想、オーバーライド、および抽象プロパティ アクセサーVirtual, sealed, override, and abstract property accessors

Avirtualプロパティ宣言では、プロパティのアクセサーが仮想であることを指定します。A virtual property declaration specifies that the accessors of the property are virtual. virtual修飾子は読み取り/書き込みプロパティの両方のアクセサーに適用されます: 読み取り/書き込みプロパティの 1 つだけのアクセサーは、仮想にすることはできません。The virtual modifier applies to both accessors of a read-write property—it is not possible for only one accessor of a read-write property to be virtual.

abstractプロパティ宣言は、プロパティのアクセサーが仮想では、アクセサーの実際の実装は提供されないことを指定します。An abstract property declaration specifies that the accessors of the property are virtual, but does not provide an actual implementation of the accessors. 代わりに、非抽象派生クラスでは、プロパティをオーバーライドすることで、アクセサーの独自の実装を提供する必要があります。Instead, non-abstract derived classes are required to provide their own implementation for the accessors by overriding the property. 抽象プロパティの宣言のアクセサーは、実際の実装を提供するため、 accessor_bodyセミコロンだけで構成されます。Because an accessor for an abstract property declaration provides no actual implementation, its accessor_body simply consists of a semicolon.

両方が含まれるプロパティの宣言、abstractoverride修飾子は、プロパティは抽象であり、基本プロパティをオーバーライドすることを指定します。A property declaration that includes both the abstract and override modifiers specifies that the property is abstract and overrides a base property. このようなプロパティのアクセサーは、抽象もあります。The accessors of such a property are also abstract.

抽象プロパティの宣言は抽象クラスでのみ許可されます (抽象クラス)。仮想継承されたプロパティのアクセサーを指定するプロパティの宣言を含めることによって派生クラスでオーバーライドできます、overrideディレクティブ。Abstract property declarations are only permitted in abstract classes (Abstract classes).The accessors of an inherited virtual property can be overridden in a derived class by including a property declaration that specifies an override directive. これと呼ばれますが、プロパティの宣言をオーバーライドするします。This is known as an overriding property declaration. オーバーライドするプロパティの宣言では、新しいプロパティを宣言していません。An overriding property declaration does not declare a new property. 代わりに、既存の仮想プロパティのアクセサーの実装を特化するだけです。Instead, it simply specializes the implementations of the accessors of an existing virtual property.

オーバーライドするプロパティの宣言では、継承されるプロパティと正確な同じアクセシビリティ修飾子、型、および名前を指定する必要があります。An overriding property declaration must specify the exact same accessibility modifiers, type, and name as the inherited property. 場合 (つまり、継承されたプロパティが読み取り専用または書き込み専用である場合)、継承されたプロパティが 1 つのアクセサーだけをオーバーライドするプロパティは、そのアクセサーだけを含める必要があります。If the inherited property has only a single accessor (i.e., if the inherited property is read-only or write-only), the overriding property must include only that accessor. 場合 (つまり、継承されたプロパティが読み取り/書き込みである場合)、継承されたプロパティが両方のアクセサーを含む、オーバーライドするプロパティは、アクセサーが 1 つまたは両方のアクセサーのいずれかを含めることができます。If the inherited property includes both accessors (i.e., if the inherited property is read-write), the overriding property can include either a single accessor or both accessors.

オーバーライドするプロパティの宣言を含めることができます、sealed修飾子。An overriding property declaration may include the sealed modifier. この修飾子を使用すると、派生クラスがさらに、プロパティをオーバーライドできなくなります。Use of this modifier prevents a derived class from further overriding the property. 封印されたプロパティのアクセサーはシールされてもいます。The accessors of a sealed property are also sealed.

宣言と呼び出しの相違点を除いて、構文、仮想、sealed、オーバーライド、および抽象アクセサーが仮想、シール、override キーワードと抽象メソッドとまったく同じ動作です。Except for differences in declaration and invocation syntax, virtual, sealed, override, and abstract accessors behave exactly like virtual, sealed, override and abstract methods. 具体的には、規則が記載仮想メソッドメソッドをオーバーライドメソッドをシール、および抽象メソッド適用としてアクセサーは、対応する形式のメソッドです。Specifically, the rules described in Virtual methods, Override methods, Sealed methods, and Abstract methods apply as if accessors were methods of a corresponding form:

  • Agetアクセサーはプロパティの型と、包含するプロパティと同じ修飾子の値を返すパラメーターなしのメソッドに相当します。A get accessor corresponds to a parameterless method with a return value of the property type and the same modifiers as the containing property.
  • Asetアクセサーはプロパティの型の 1 つの値を持つパラメーターを持つメソッドに相当するvoid種類、およびそれを含むプロパティと同じ修飾子を返します。A set accessor corresponds to a method with a single value parameter of the property type, a void return type, and the same modifiers as the containing property.

In the example

abstract class A
{
    int y;

    public virtual int X {
        get { return 0; }
    }

    public virtual int Y {
        get { return y; }
        set { y = value; }
    }

    public abstract int Z { get; set; }
}

X 仮想の読み取り専用プロパティは、Y仮想の読み取り/書き込みプロパティとZは抽象の読み取り/書き込みプロパティです。X is a virtual read-only property, Y is a virtual read-write property, and Z is an abstract read-write property. Z抽象クラスでは、含んでいるクラスAする必要がありますも抽象として宣言します。Because Z is abstract, the containing class A must also be declared abstract.

派生したクラスA次に示します。A class that derives from A is show below:

class B: A
{
    int z;

    public override int X {
        get { return base.X + 1; }
    }

    public override int Y {
        set { base.Y = value < 0? 0: value; }
    }

    public override int Z {
        get { return z; }
        set { z = value; }
    }
}

ここでは、宣言のXY、およびZプロパティの宣言をオーバーライドします。Here, the declarations of X, Y, and Z are overriding property declarations. 各プロパティの宣言は、アクセシビリティ修飾子、型、および対応する継承されたプロパティの名前を正確に一致します。Each property declaration exactly matches the accessibility modifiers, type, and name of the corresponding inherited property. getのアクセサーXsetのアクセサーYを使用して、baseキーワードを使って、継承されたアクセサーにアクセスします。The get accessor of X and the set accessor of Y use the base keyword to access the inherited accessors. 宣言Z両方の抽象アクセサーのオーバーライド: そのため、未処理の抽象関数のメンバーではありませんBB非抽象クラスにすることが許可されています。The declaration of Z overrides both abstract accessors—thus, there are no outstanding abstract function members in B, and B is permitted to be a non-abstract class.

プロパティとして宣言されている場合、 override、オーバーライドされるアクセサーをオーバーライドするコードにアクセスできる必要があります。When a property is declared as an override, any overridden accessors must be accessible to the overriding code. さらに、プロパティまたはインデクサー自体の両方のおよびアクセサーの宣言されたアクセシビリティでは、オーバーライドされたメンバーおよびアクセサーの一致する必要があります。In addition, the declared accessibility of both the property or indexer itself, and of the accessors, must match that of the overridden member and accessors. 例:For example:

public class B
{
    public virtual int P {
        protected set {...}
        get {...}
    }
}

public class D: B
{
    public override int P {
        protected set {...}            // Must specify protected here
        get {...}                      // Must not have a modifier here
    }
}

イベントEvents

イベントオブジェクトや通知を提供するクラスのメンバーであります。An event is a member that enables an object or class to provide notifications. クライアントは、イベントの実行可能コードを追加指定することによってイベント ハンドラーします。Clients can attach executable code for events by supplying event handlers.

使用してイベントが宣言されたevent_declaration: %sEvents are declared using event_declarations:

event_declaration
    : attributes? event_modifier* 'event' type variable_declarators ';'
    | attributes? event_modifier* 'event' type member_name '{' event_accessor_declarations '}'
    ;

event_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | event_modifier_unsafe
    ;

event_accessor_declarations
    : add_accessor_declaration remove_accessor_declaration
    | remove_accessor_declaration add_accessor_declaration
    ;

add_accessor_declaration
    : attributes? 'add' block
    ;

remove_accessor_declaration
    : attributes? 'remove' block
    ;

Event_declarationのセットを含めることができます属性(属性) と有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)、 new (new 修飾子)、 static (静的およびインスタンス メソッド)、 virtual (仮想メソッド)、 override (メソッドをオーバーライド)、 sealed (メソッドをシール)、 abstract (抽象メソッド)、およびextern (外部メソッド) 修飾子。An event_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), static (Static and instance methods), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

イベント宣言では、メソッドの宣言と同じ規則 (メソッド) 修飾子の組み合わせが無効です。Event declarations are subject to the same rules as method declarations (Methods) with regard to valid combinations of modifiers.

イベントの宣言がある必要があります、 delegate_type (参照型)、およびdelegate_type以上である必要がありますとしてイベント自体としてアクセスできるように (アクセシビリティ制約)。The type of an event declaration must be a delegate_type (Reference types), and that delegate_type must be at least as accessible as the event itself (Accessibility constraints).

イベントの宣言を含めることができますevent_accessor_declarationsします。An event declaration may include event_accessor_declarations. ただし、そうでない場合、extern 以外の場合の非抽象イベントをコンパイラによってに自動的に (フィールドのようなイベント) は、extern イベント アクセサーが外部から提供されます。However, if it does not, for non-extern, non-abstract events, the compiler supplies them automatically (Field-like events); for extern events, the accessors are provided externally.

イベントの宣言を省略したevent_accessor_declarations 1 つまたは複数のイベントを定義します: のごとに 1 つ、 variable_declarator秒。An event declaration that omits event_accessor_declarations defines one or more events—one for each of the variable_declarators. 属性と修飾子などで宣言されたメンバーのすべてに適用されます、 event_declarationします。The attributes and modifiers apply to all of the members declared by such an event_declaration.

コンパイル時エラーには、 event_declaration両方を含める、abstract修飾子と中かっこで区切られたevent_accessor_declarationsします。It is a compile-time error for an event_declaration to include both the abstract modifier and brace-delimited event_accessor_declarations.

イベントの宣言が含まれています、extern修飾子は、イベントはモード、外部イベントします。When an event declaration includes an extern modifier, the event is said to be an external event. 両方を追加するエラーです、外部のイベント宣言は実際の実装を提供しないため、extern修飾子とevent_accessor_declarationsします。Because an external event declaration provides no actual implementation, it is an error for it to include both the extern modifier and event_accessor_declarations.

コンパイル時エラーには、 variable_declaratorイベント宣言でのabstractまたはexternal修飾子を含める、 variable_initializerします。It is a compile-time error for a variable_declarator of an event declaration with an abstract or external modifier to include a variable_initializer.

イベントの左側のオペランドとして使用できる、+=-=演算子 (イベント割り当て)。An event can be used as the left-hand operand of the += and -= operators (Event assignment). これらの演算子を使用、それぞれにイベント ハンドラーをアタッチするか、イベントからイベント ハンドラーを削除して、イベントのアクセス修飾子は、このような操作が許可されているコンテキストを制御します。These operators are used, respectively, to attach event handlers to or to remove event handlers from an event, and the access modifiers of the event control the contexts in which such operations are permitted.

+=-=はイベント、外部コードを宣言する型の外部イベントが許可されている唯一の操作できます追加し、イベントのハンドラーを削除するが、ことはできません、他の方法で取得またはイベントの基になるリストを変更ハンドラー。Since += and -= are the only operations that are permitted on an event outside the type that declares the event, external code can add and remove handlers for an event, but cannot in any other way obtain or modify the underlying list of event handlers.

フォームの操作でx += yまたはx -= yxイベントは、の宣言を含む型の外部参照が行わx、操作の結果は、型を持つvoid(直す必要はありません型xの値を持つx代入された後)。In an operation of the form x += y or x -= y, when x is an event and the reference takes place outside the type that contains the declaration of x, the result of the operation has type void (as opposed to having the type of x, with the value of x after the assignment). このルールは、イベントの基になるデリゲートを直接調べることから、外部コードを禁止します。This rule prohibits external code from indirectly examining the underlying delegate of an event.

次の例のインスタンスにイベント ハンドラーをアタッチする方法を示しています、Buttonクラス。The following example shows how event handlers are attached to instances of the Button class:

public delegate void EventHandler(object sender, EventArgs e);

public class Button: Control
{
    public event EventHandler Click;
}

public class LoginDialog: Form
{
    Button OkButton;
    Button CancelButton;

    public LoginDialog() {
        OkButton = new Button(...);
        OkButton.Click += new EventHandler(OkButtonClick);
        CancelButton = new Button(...);
        CancelButton.Click += new EventHandler(CancelButtonClick);
    }

    void OkButtonClick(object sender, EventArgs e) {
        // Handle OkButton.Click event
    }

    void CancelButtonClick(object sender, EventArgs e) {
        // Handle CancelButton.Click event
    }
}

ここでは、LoginDialogインスタンス コンス トラクターでは、2 つ作成されますButtonインスタンスし、イベント ハンドラーをアタッチします、Clickイベント。Here, the LoginDialog instance constructor creates two Button instances and attaches event handlers to the Click events.

フィールドのようなイベントField-like events

クラスまたはイベントの宣言を含む構造体のプログラム テキスト内のフィールドのような特定のイベントを使用できます。Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. この方法で使用する、イベントすることはできませんabstractまたはextern、明示的に含めることはできませんとevent_accessor_declarationsします。To be used in this way, an event must not be abstract or extern, and must not explicitly include event_accessor_declarations. このような場合は、フィールドを許容する任意のコンテキストで使用できます。Such an event can be used in any context that permits a field. フィールドには、デリゲートが含まれています (デリゲート) これは、イベントに追加されているイベント ハンドラーの一覧を指します。The field contains a delegate (Delegates) which refers to the list of event handlers that have been added to the event. イベント ハンドラーが追加されていない場合、フィールドが含まれますnullします。If no event handlers have been added, the field contains null.

In the example

public delegate void EventHandler(object sender, EventArgs e);

public class Button: Control
{
    public event EventHandler Click;

    protected void OnClick(EventArgs e) {
        if (Click != null) Click(this, e);
    }

    public void Reset() {
        Click = null;
    }
}

Click 内のフィールドとして提供される、Buttonクラス。Click is used as a field within the Button class. 例に示すようフィールド検査、変更、および使用できるデリゲートの呼び出し式で。As the example demonstrates, the field can be examined, modified, and used in delegate invocation expressions. OnClickメソッドで、Buttonクラスが「生成」、Clickイベント。The OnClick method in the Button class "raises" the Click event. イベントを発生させるという概念は、イベントによって表されるデリゲートの呼び出しとまったく同じです。したがって、イベントを発生させるための特殊な言語コンストラクトはありません。The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events. デリゲートの呼び出しは、デリゲートが null でないことを確認するチェックに続くことに注意してください。Note that the delegate invocation is preceded by a check that ensures the delegate is non-null.

宣言の外側、Buttonクラス、Clickのみの左側にあるメンバーを使用できます、+=-=の演算子Outside the declaration of the Button class, the Click member can only be used on the left-hand side of the += and -= operators, as in

b.Click += new EventHandler(...);

呼び出しリストにデリゲートを追加するClickイベント、およびwhich appends a delegate to the invocation list of the Click event, and

b.Click -= new EventHandler(...);

呼び出しリストからデリゲートを削除するClickイベント。which removes a delegate from the invocation list of the Click event.

フィールドのようにイベントをコンパイルするときに、コンパイラは自動的に、デリゲートを保持するストレージを作成し、追加または削除するデリゲート フィールドのイベント ハンドラーをイベントのアクセサーを作成します。When compiling a field-like event, the compiler automatically creates storage to hold the delegate, and creates accessors for the event that add or remove event handlers to the delegate field. 追加と削除操作はスレッド セーフであると可能性があります (ただしする必要はありません) 中に実行するロックを保持 (lock ステートメント) インスタンスのイベントを格納するオブジェクト、または型のオブジェクト (Anonymousオブジェクト作成式) の静的イベント。The addition and removal operations are thread safe, and may (but are not required to) be done while holding the lock (The lock statement) on the containing object for an instance event, or the type object (Anonymous object creation expressions) for a static event.

したがって、インスタンス イベントの形式の宣言:Thus, an instance event declaration of the form:

class X
{
    public event D Ev;
}

等価のものにコンパイルされます。will be compiled to something equivalent to:

class X
{
    private D __Ev;  // field to hold the delegate

    public event D Ev {
        add {
            /* add the delegate in a thread safe way */
        }

        remove {
            /* remove the delegate in a thread safe way */
        }
    }
}

クラス内でXへの参照Evの左側にある、+=-=演算子の追加が発生して remove アクセサーを呼び出すことができます。Within the class X, references to Ev on the left-hand side of the += and -= operators cause the add and remove accessors to be invoked. その他のすべての参照をEv隠しフィールドを参照にコンパイルされます__Ev代わりに (メンバー アクセス)。All other references to Ev are compiled to reference the hidden field __Ev instead (Member access). 名前"__Ev"は任意です。 非表示フィールドがあって任意の名前または名前のないすべての。The name "__Ev" is arbitrary; the hidden field could have any name or no name at all.

イベント アクセサーEvent accessors

イベントの宣言は通常省略event_accessor_declarationsButton上記の例です。Event declarations typically omit event_accessor_declarations, as in the Button example above. そのため、1 つの状況としてには、イベントごとに 1 つのフィールドのストレージ コストが許容されない場合が含まれます。One situation for doing so involves the case in which the storage cost of one field per event is not acceptable. このような場合は、クラスを含めることができますevent_accessor_declarationsおよびイベント ハンドラーの一覧を格納するため、プライベート メカニズムを使用します。In such cases, a class can include event_accessor_declarations and use a private mechanism for storing the list of event handlers.

Event_accessor_declarationsイベントの追加と削除イベント ハンドラーに関連付けられている実行可能なステートメントを指定します。The event_accessor_declarations of an event specify the executable statements associated with adding and removing event handlers.

アクセサーの宣言から成る、 add_accessor_declarationremove_accessor_declarationします。The accessor declarations consist of an add_accessor_declaration and a remove_accessor_declaration. 各アクセサーの宣言は、トークンのaddまたはremove続けて、ブロックします。Each accessor declaration consists of the token add or remove followed by a block. ブロックに関連付けられている、 add_accessor_declarationイベント ハンドラーを追加すると、ときに実行するステートメントを指定します、ブロックに関連付けられています。remove_accessor_declarationイベント ハンドラーが削除されるときに実行するステートメントを指定します。The block associated with an add_accessor_declaration specifies the statements to execute when an event handler is added, and the block associated with a remove_accessor_declaration specifies the statements to execute when an event handler is removed.

add_accessor_declarationremove_accessor_declarationイベントの種類の 1 つの値を持つパラメーターを持つメソッドに対応し、void型を返します。Each add_accessor_declaration and remove_accessor_declaration corresponds to a method with a single value parameter of the event type and a void return type. イベント アクセサーの暗黙のパラメーターの名前はvalueします。The implicit parameter of an event accessor is named value. イベントはイベント割り当てで使用する適切なイベントのアクセサーが使用されます。When an event is used in an event assignment, the appropriate event accessor is used. 具体的には、代入演算子がある場合+=代入演算子は、add アクセサーを使用すると、 -= remove アクセサーが使用されます。Specifically, if the assignment operator is += then the add accessor is used, and if the assignment operator is -= then the remove accessor is used. いずれの場合も、代入演算子の右側のオペランドは、イベント アクセサーに引数として使用されます。In either case, the right-hand operand of the assignment operator is used as the argument to the event accessor. ブロック、 add_accessor_declarationまたはremove_accessor_declarationの規則に従う必要がありますvoidで説明したメソッドメソッド本体します。The block of an add_accessor_declaration or a remove_accessor_declaration must conform to the rules for void methods described in Method body. 具体的には、return式を指定するこのようなブロック内のステートメントは許可されていません。In particular, return statements in such a block are not permitted to specify an expression.

イベント アクセサーは、という名前のパラメーターを暗黙的にためvalue、その名前を持つイベント アクセサーでローカル変数または定数が宣言されているは、コンパイル時エラー。Since an event accessor implicitly has a parameter named value, it is a compile-time error for a local variable or constant declared in an event accessor to have that name.

In the example

class Control: Component
{
    // Unique keys for events
    static readonly object mouseDownEventKey = new object();
    static readonly object mouseUpEventKey = new object();

    // Return event handler associated with key
    protected Delegate GetEventHandler(object key) {...}

    // Add event handler associated with key
    protected void AddEventHandler(object key, Delegate handler) {...}

    // Remove event handler associated with key
    protected void RemoveEventHandler(object key, Delegate handler) {...}

    // MouseDown event
    public event MouseEventHandler MouseDown {
        add { AddEventHandler(mouseDownEventKey, value); }
        remove { RemoveEventHandler(mouseDownEventKey, value); }
    }

    // MouseUp event
    public event MouseEventHandler MouseUp {
        add { AddEventHandler(mouseUpEventKey, value); }
        remove { RemoveEventHandler(mouseUpEventKey, value); }
    }

    // Invoke the MouseUp event
    protected void OnMouseUp(MouseEventArgs args) {
        MouseEventHandler handler; 
        handler = (MouseEventHandler)GetEventHandler(mouseUpEventKey);
        if (handler != null)
            handler(this, args);
    }
}

Controlクラスは、イベント用内部ストレージ メカニズムを実装します。the Control class implements an internal storage mechanism for events. AddEventHandlerメソッドは、キーを持つデリゲート値を関連付けます、GetEventHandlerメソッドは、キーに関連付けられているデリゲートを返します、RemoveEventHandlerメソッドは、指定したイベントのイベント ハンドラーとしてデリゲートを削除します。The AddEventHandler method associates a delegate value with a key, the GetEventHandler method returns the delegate currently associated with a key, and the RemoveEventHandler method removes a delegate as an event handler for the specified event. 多くの場合、基になるストレージ メカニズムは関連付けるためのコストはありませんように作られています、nullキーを持つ値を委任し、未処理のイベント ストレージ消費しないためです。Presumably, the underlying storage mechanism is designed such that there is no cost for associating a null delegate value with a key, and thus unhandled events consume no storage.

静的およびインスタンスのイベントStatic and instance events

イベントの宣言が含まれています、static修飾子は、イベントはモード、静的イベントします。When an event declaration includes a static modifier, the event is said to be a static event. ない場合static修飾子が存在する、イベントはモード、インスタンス イベントします。When no static modifier is present, the event is said to be an instance event.

静的イベントは、特定のインスタンスに関連付けられていないを参照すると、コンパイル時エラーthis静的イベントのアクセサーでします。A static event is not associated with a specific instance, and it is a compile-time error to refer to this in the accessors of a static event.

インスタンス イベントは、クラスの特定のインスタンスに関連付けられ、としてこのインスタンスにアクセスできるthis(このアクセス) でそのイベントのアクセサー。An instance event is associated with a given instance of a class, and this instance can be accessed as this (This access) in the accessors of that event.

イベントが参照されている場合、 member_access (メンバー アクセス) フォームのE.M場合は、M静的なイベントは、 E を含む型を表す必要がありますM、場合Mインスタンス イベントは、電子メールに含まれる型のインスタンスを表す必要がありますMします。When an event is referenced in a member_access (Member access) of the form E.M, if M is a static event, E must denote a type containing M, and if M is an instance event, E must denote an instance of a type containing M.

静的な違いは、インスタンス メンバーの説明とでさらに静的メンバーとインスタンス メンバーThe differences between static and instance members are discussed further in Static and instance members.

封印されて、仮想、オーバーライド、および抽象イベント アクセサーVirtual, sealed, override, and abstract event accessors

Avirtualイベント宣言では、そのイベントのアクセサーが仮想であることを指定します。A virtual event declaration specifies that the accessors of that event are virtual. virtual修飾子は、イベントの両方のアクセサーに適用されます。The virtual modifier applies to both accessors of an event.

abstractイベント宣言は、イベントのアクセサーが仮想では、アクセサーの実際の実装は提供されないことを指定します。An abstract event declaration specifies that the accessors of the event are virtual, but does not provide an actual implementation of the accessors. 代わりに、非抽象派生クラスでは、イベントをオーバーライドすることで、アクセサーの独自の実装を提供する必要があります。Instead, non-abstract derived classes are required to provide their own implementation for the accessors by overriding the event. 抽象イベントの宣言は実際の実装を提供しないため、中かっこで区切られたを提供できませんevent_accessor_declarationsします。Because an abstract event declaration provides no actual implementation, it cannot provide brace-delimited event_accessor_declarations.

両方が含まれるイベントの宣言、abstractoverride修飾子は、イベントは抽象であり、基本イベントをオーバーライドを指定します。An event declaration that includes both the abstract and override modifiers specifies that the event is abstract and overrides a base event. このようなイベントのアクセサーは、抽象もあります。The accessors of such an event are also abstract.

抽象イベントの宣言は抽象クラスでのみ許可されます (抽象クラス)。Abstract event declarations are only permitted in abstract classes (Abstract classes).

継承された仮想イベントのアクセサーを指定するイベントの宣言を含めることによって派生クラスでオーバーライドできます、override修飾子。The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an override modifier. これと呼ばれますが、イベントの宣言をオーバーライドするします。This is known as an overriding event declaration. オーバーライドするイベントの宣言では、新しいイベントを宣言していません。An overriding event declaration does not declare a new event. 代わりに、既存の仮想イベントのアクセサーの実装を特化するだけです。Instead, it simply specializes the implementations of the accessors of an existing virtual event.

オーバーライドするイベントの宣言では、上書きされるイベントとして正確な同じアクセシビリティ修飾子、型、および名前を指定する必要があります。An overriding event declaration must specify the exact same accessibility modifiers, type, and name as the overridden event.

オーバーライドするイベントの宣言を含めることができます、sealed修飾子。An overriding event declaration may include the sealed modifier. この修飾子を使用すると、派生クラスがさらに、イベントをオーバーライドできなくなります。Use of this modifier prevents a derived class from further overriding the event. 封印されたイベントのアクセサーはシールされてもいます。The accessors of a sealed event are also sealed.

コンパイル時エラーをオーバーライドする側のイベントの宣言を含めるには、new修飾子。It is a compile-time error for an overriding event declaration to include a new modifier.

宣言と呼び出しの相違点を除いて、構文、仮想、sealed、オーバーライド、および抽象アクセサーが仮想、シール、override キーワードと抽象メソッドとまったく同じ動作です。Except for differences in declaration and invocation syntax, virtual, sealed, override, and abstract accessors behave exactly like virtual, sealed, override and abstract methods. 具体的には、規則が記載仮想メソッドメソッドをオーバーライドメソッドをシール、および抽象メソッド適用としてアクセサーは、対応する形式のメソッドをでした。Specifically, the rules described in Virtual methods, Override methods, Sealed methods, and Abstract methods apply as if accessors were methods of a corresponding form. 各アクセサーは、イベントの種類の 1 つの値を持つパラメーターを持つメソッドに相当するvoid種類、および、含んでいるイベントと同じ修飾子を返します。Each accessor corresponds to a method with a single value parameter of the event type, a void return type, and the same modifiers as the containing event.

インデクサーIndexers

インデクサーは、配列と同じ方法でインデックスを作成するオブジェクトのメンバーです。An indexer is a member that enables an object to be indexed in the same way as an array. 使用してインデクサーを宣言indexer_declaration: %sIndexers are declared using indexer_declarations:

indexer_declaration
    : attributes? indexer_modifier* indexer_declarator indexer_body
    ;

indexer_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | indexer_modifier_unsafe
    ;

indexer_declarator
    : type 'this' '[' formal_parameter_list ']'
    | type interface_type '.' 'this' '[' formal_parameter_list ']'
    ;

indexer_body
    : '{' accessor_declarations '}' 
    | '=>' expression ';'
    ;

Indexer_declarationのセットを含めることができます属性(属性) と有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)、 new (new 修飾子)、 virtual (仮想メソッド)、 override (メソッドをオーバーライド)、 sealed (メソッドをシール)、 abstract (抽象メソッド)、およびextern(外部メソッド) 修飾子。An indexer_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

インデクサーの宣言では、メソッドの宣言と同じ規則 (メソッド) 有効な修飾子の組み合わせ、static 修飾子が 1 つの例外は許可されていません、インデクサーの宣言。Indexer declarations are subject to the same rules as method declarations (Methods) with regard to valid combinations of modifiers, with the one exception being that the static modifier is not permitted on an indexer declaration.

修飾子virtualoverride、およびabstractは 1 つのケースを除く相互に排他的です。The modifiers virtual, override, and abstract are mutually exclusive except in one case. abstractoverride抽象インデクサーが仮想の 1 つをオーバーライドするために、修飾子をまとめて使用することです。The abstract and override modifiers may be used together so that an abstract indexer can override a virtual one.

インデクサーの宣言は、宣言によって導入されるインデクサーの要素の型を指定します。The type of an indexer declaration specifies the element type of the indexer introduced by the declaration. インデクサーは、明示的なインターフェイス メンバーの実装、しない限り、キーワードの後にthisします。Unless the indexer is an explicit interface member implementation, the type is followed by the keyword this. 明示的なインターフェイス メンバーの実装、が続く、 interface_type、"."、およびキーワードthisします。For an explicit interface member implementation, the type is followed by an interface_type, a ".", and the keyword this. 他のメンバーとは異なりインデクサーにはユーザー定義の名前がありません。Unlike other members, indexers do not have user-defined names.

Formal_parameter_listインデクサーのパラメーターを指定します。The formal_parameter_list specifies the parameters of the indexer. メソッドに対応するインデクサーの仮パラメーター リスト (メソッドのパラメーター) には少なくとも 1 つのパラメーターを指定することを除いて、および、refoutパラメーター修飾子は許可されていません.The formal parameter list of an indexer corresponds to that of a method (Method parameters), except that at least one parameter must be specified, and that the ref and out parameter modifiers are not permitted.

で参照される型のそれぞれのインデクサーのformal_parameter_list少なくとも、インデクサー自体と同程度にアクセスできる必要があります (アクセシビリティ制約).The type of an indexer and each of the types referenced in the formal_parameter_list must be at least as accessible as the indexer itself (Accessibility constraints).

Indexer_bodyので構成するか、アクセサー本体または式本体します。An indexer_body may either consist of an accessor body or an expression body. アクセサーの本体でaccessor_declarations、これで囲む必要があります"{「と」}"トークンは、アクセサーを宣言する (アクセサー) プロパティの。In an accessor body, accessor_declarations, which must be enclosed in "{" and "}" tokens, declare the accessors (Accessors) of the property. アクセサーは、読み取りと書き込みのプロパティに関連付けられている実行可能ステートメントを指定します。The accessors specify the executable statements associated with reading and writing the property.

構成される式の本体"=>"の後に式Eセミコロンはステートメント本体内でまったく同じですが、 { get { return E; } }、ことができますのみため、インデクサーの get アクセス操作子のみを指定する、get アクセス操作子の結果が1 つの式で指定されます。An expression body consisting of "=>" followed by an expression E and a semicolon is exactly equivalent to the statement body { get { return E; } }, and can therefore only be used to specify getter-only indexers where the result of the getter is given by a single expression.

インデクサーの要素にアクセスするための構文と同じでは配列要素が、インデクサーの要素は変数としては分類されません。Even though the syntax for accessing an indexer element is the same as that for an array element, an indexer element is not classified as a variable. したがってとしてインデクサーの要素を渡すことはできません、refまたはout引数。Thus, it is not possible to pass an indexer element as a ref or out argument.

インデクサーの仮パラメーター リストは、署名を定義します (シグネチャとオーバー ロード) のインデクサー。The formal parameter list of an indexer defines the signature (Signatures and overloading) of the indexer. 具体的には、インデクサーのシグネチャは、その仮パラメーターの型と数で構成されます。Specifically, the signature of an indexer consists of the number and types of its formal parameters. 要素型と仮パラメーターの名前は、インデクサーのシグネチャの一部ではないです。The element type and names of the formal parameters are not part of an indexer's signature.

インデクサーのシグネチャは、同じクラスで宣言されている他のすべてのインデクサーの署名とは異なる必要があります。The signature of an indexer must differ from the signatures of all other indexers declared in the same class.

インデクサーとプロパティは、概念的によく似ていますが、次の点で異なります。Indexers and properties are very similar in concept, but differ in the following ways:

  • プロパティは、インデクサーは、そのシグネチャで識別される一方、名前によって識別されます。A property is identified by its name, whereas an indexer is identified by its signature.
  • プロパティを通じてアクセス、 simple_name (簡易名) またはmember_access (メンバー アクセス) であるのに対し、インデクサー要素は、 element_access (インデクサー アクセス)。A property is accessed through a simple_name (Simple names) or a member_access (Member access), whereas an indexer element is accessed through an element_access (Indexer access).
  • プロパティをstaticメンバー、インデクサーはインスタンス メンバーでは常にします。A property can be a static member, whereas an indexer is always an instance member.
  • Aget一方、プロパティのアクセサーがパラメーターなしのメソッドに対応するgetインデクサーのアクセサーは、インデクサーと同じ仮パラメーター リストを持つメソッドに相当します。A get accessor of a property corresponds to a method with no parameters, whereas a get accessor of an indexer corresponds to a method with the same formal parameter list as the indexer.
  • Asetという名前の 1 つのパラメーターのプロパティのアクセサーがメソッドに対応valueであるのに対し、setインデクサーのアクセサーは、インデクサー、および追加のパラメーターとして同じ仮パラメーター リストを持つメソッドに相当名前付きvalueします。A set accessor of a property corresponds to a method with a single parameter named value, whereas a set accessor of an indexer corresponds to a method with the same formal parameter list as the indexer, plus an additional parameter named value.
  • インデクサー パラメーターと同じ名前でローカル変数を宣言するインデクサーのアクセサーのコンパイル時エラーになります。It is a compile-time error for an indexer accessor to declare a local variable with the same name as an indexer parameter.
  • 構文を使用して継承されたプロパティにアクセスをオーバーライドするプロパティの宣言でbase.Pここで、Pプロパティの名前です。In an overriding property declaration, the inherited property is accessed using the syntax base.P, where P is the property name. 構文を使用して、オーバーライドするインデクサーの宣言から継承されたインデクサーにアクセスはbase[E]ここで、E式のコンマ区切り一覧を示します。In an overriding indexer declaration, the inherited indexer is accessed using the syntax base[E], where E is a comma separated list of expressions.
  • 「自動的に実装されたインデクサー」の概念はありません。There is no concept of an "automatically implemented indexer". セミコロンのアクセサーを持つ非抽象、非外部のインデクサーにエラーになります。It is an error to have a non-abstract, non-external indexer with semicolon accessors.

これらの違いとは別にすべてのルールが定義されているアクセサー自動実装プロパティインデクサー アクセサーもプロパティ アクセサーに適用します。Aside from these differences, all rules defined in Accessors and Automatically implemented properties apply to indexer accessors as well as to property accessors.

インデクサーの宣言が含まれています、extern修飾子は、インデクサーはモード、外部インデクサーします。When an indexer declaration includes an extern modifier, the indexer is said to be an external indexer. 外部のインデクサーの宣言は、それぞれの実際の実装を提供するため、 accessor_declarationsをセミコロンで構成されます。Because an external indexer declaration provides no actual implementation, each of its accessor_declarations consists of a semicolon.

次の例の宣言をBitArrayビット配列内の個々 のビットにアクセスするためのインデクサーを実装するクラス。The example below declares a BitArray class that implements an indexer for accessing the individual bits in the bit array.

using System;

class BitArray
{
    int[] bits;
    int length;

    public BitArray(int length) {
        if (length < 0) throw new ArgumentException();
        bits = new int[((length - 1) >> 5) + 1];
        this.length = length;
    }

    public int Length {
        get { return length; }
    }

    public bool this[int index] {
        get {
            if (index < 0 || index >= length) {
                throw new IndexOutOfRangeException();
            }
            return (bits[index >> 5] & 1 << index) != 0;
        }
        set {
            if (index < 0 || index >= length) {
                throw new IndexOutOfRangeException();
            }
            if (value) {
                bits[index >> 5] |= 1 << index;
            }
            else {
                bits[index >> 5] &= ~(1 << index);
            }
        }
    }
}

インスタンス、BitArrayクラスは、対応するよりも大幅に削減のメモリを消費bool[](前者の各値の代わりに 1 ビットのみが占めるため、後者の 1 バイト) と同じ操作、ようになりますが、bool[]します。An instance of the BitArray class consumes substantially less memory than a corresponding bool[] (since each value of the former occupies only one bit instead of the latter's one byte), but it permits the same operations as a bool[].

CountPrimesクラスで使用するBitArrayと 1 と指定された最大値の間の素数の数を計算する従来の「エラトステネス」アルゴリズム。The following CountPrimes class uses a BitArray and the classical "sieve" algorithm to compute the number of primes between 1 and a given maximum:

class CountPrimes
{
    static int Count(int max) {
        BitArray flags = new BitArray(max + 1);
        int count = 1;
        for (int i = 2; i <= max; i++) {
            if (!flags[i]) {
                for (int j = i * 2; j <= max; j += i) flags[j] = true;
                count++;
            }
        }
        return count;
    }

    static void Main(string[] args) {
        int max = int.Parse(args[0]);
        int count = Count(max);
        Console.WriteLine("Found {0} primes between 1 and {1}", count, max);
    }
}

なお、構文の要素にアクセスするため、BitArrayが正確に同じである、bool[]します。Note that the syntax for accessing elements of the BitArray is precisely the same as for a bool[].

次の例では、2 つのパラメーターを持つインデクサーを持つ 26 * 10 グリッド クラスを示します。The following example shows a 26 * 10 grid class that has an indexer with two parameters. 大文字または小文字の文字 A ~ Z の範囲の最初のパラメーターが必要し、する 0 ~ 9 の範囲の整数である 2 つ目が必要です。The first parameter is required to be an upper- or lowercase letter in the range A-Z, and the second is required to be an integer in the range 0-9.

using System;

class Grid
{
    const int NumRows = 26;
    const int NumCols = 10;

    int[,] cells = new int[NumRows, NumCols];

    public int this[char c, int col] {
        get {
            c = Char.ToUpper(c);
            if (c < 'A' || c > 'Z') {
                throw new ArgumentException();
            }
            if (col < 0 || col >= NumCols) {
                throw new IndexOutOfRangeException();
            }
            return cells[c - 'A', col];
        }

        set {
            c = Char.ToUpper(c);
            if (c < 'A' || c > 'Z') {
                throw new ArgumentException();
            }
            if (col < 0 || col >= NumCols) {
                throw new IndexOutOfRangeException();
            }
            cells[c - 'A', col] = value;
        }
    }
}

インデクサーのオーバー ロードIndexer overloading

インデクサーのオーバー ロード解決規則が記載されて型推論します。The indexer overload resolution rules are described in Type inference.

演算子Operators

演算子は、クラスのインスタンスに適用できる式の演算子の意味を定義するメンバーです。An operator is a member that defines the meaning of an expression operator that can be applied to instances of the class. 演算子を使用して宣言operator_declaration: %sOperators are declared using operator_declarations:

operator_declaration
    : attributes? operator_modifier+ operator_declarator operator_body
    ;

operator_modifier
    : 'public'
    | 'static'
    | 'extern'
    | operator_modifier_unsafe
    ;

operator_declarator
    : unary_operator_declarator
    | binary_operator_declarator
    | conversion_operator_declarator
    ;

unary_operator_declarator
    : type 'operator' overloadable_unary_operator '(' type identifier ')'
    ;

overloadable_unary_operator
    : '+' | '-' | '!' | '~' | '++' | '--' | 'true' | 'false'
    ;

binary_operator_declarator
    : type 'operator' overloadable_binary_operator '(' type identifier ',' type identifier ')'
    ;

overloadable_binary_operator
    : '+'   | '-'   | '*'   | '/'   | '%'   | '&'   | '|'   | '^'   | '<<'
    | right_shift | '=='  | '!='  | '>'   | '<'   | '>='  | '<='
    ;

conversion_operator_declarator
    : 'implicit' 'operator' type '(' type identifier ')'
    | 'explicit' 'operator' type '(' type identifier ')'
    ;

operator_body
    : block
    | '=>' expression ';'
    | ';'
    ;

オーバー ロードされた演算子の 3 つのカテゴリがあります。単項演算子 (単項演算子)、二項演算子 (二項演算子)、および変換演算子 (変換演算子)。There are three categories of overloadable operators: Unary operators (Unary operators), binary operators (Binary operators), and conversion operators (Conversion operators).

Operator_bodyがいずれかをセミコロン、ステートメント本体または式本体します。The operator_body is either a semicolon, a statement body or an expression body. ステートメント本体から成る、ブロック演算子が呼び出されたときに実行するステートメントを指定します。A statement body consists of a block, which specifies the statements to execute when the operator is invoked. ブロック値を返すための規則に準拠している必要がありますで説明したメソッドメソッド本体します。The block must conform to the rules for value-returning methods described in Method body. 式の本体から成る=>式およびセミコロンが続くし、演算子が呼び出されたときに実行する 1 つの式を表します。An expression body consists of => followed by an expression and a semicolon, and denotes a single expression to perform when the operator is invoked.

extern 、演算子、 operator_bodyセミコロンだけで構成されます。For extern operators, the operator_body consists simply of a semicolon. その他のすべての演算子、 operator_bodyはブロック本体または式の本体。For all other operators, the operator_body is either a block body or an expression body.

すべての演算子の宣言に、次の規則が適用されます。The following rules apply to all operator declarations:

  • 演算子の宣言は、両方を含める必要があります、publicstatic修飾子。An operator declaration must include both a public and a static modifier.
  • 演算子のパラメーターはパラメーターの値である必要があります (パラメーターの値)。The parameter(s) of an operator must be value parameters (Value parameters). 演算子の宣言を指定すると、コンパイル時エラーrefまたはoutパラメーター。It is a compile-time error for an operator declaration to specify ref or out parameters.
  • 演算子のシグネチャ (単項演算子二項演算子変換演算子) で宣言されているその他のすべての演算子のシグネチャが異なる場合、同じクラスです。The signature of an operator (Unary operators, Binary operators, Conversion operators) must differ from the signatures of all other operators declared in the same class.
  • 演算子の宣言で参照されるすべての型は、少なくとも、演算子自体と同程度にアクセスである必要があります (アクセシビリティ制約)。All types referenced in an operator declaration must be at least as accessible as the operator itself (Accessibility constraints).
  • 演算子の宣言内で複数回、同じ修飾子のエラーになります。It is an error for the same modifier to appear multiple times in an operator declaration.

各演算子のカテゴリは、次のセクションで説明したように、制限を課しています。Each operator category imposes additional restrictions, as described in the following sections.

他のメンバーのような基底クラスで宣言されている演算子は、派生クラスによって継承されます。Like other members, operators declared in a base class are inherited by derived classes. 演算子の宣言は、常に、クラスまたは構造体への参加、演算子のシグネチャ、演算子が宣言されている必要があるために、派生クラスで宣言された基本クラスで宣言されている演算子が非表示にするオペレーターのことはできません。Because operator declarations always require the class or struct in which the operator is declared to participate in the signature of the operator, it is not possible for an operator declared in a derived class to hide an operator declared in a base class. つまり、new修飾子が、必要なことはありませんし、ためでは使用できない、演算子の宣言。Thus, the new modifier is never required, and therefore never permitted, in an operator declaration.

単項および二項演算子の追加情報が記載されて演算子します。Additional information on unary and binary operators can be found in Operators.

変換演算子の追加情報が記載されてユーザー定義の変換します。Additional information on conversion operators can be found in User-defined conversions.

単項演算子Unary operators

単項演算子の宣言に、次の規則が適用されます、Tはクラスまたは演算子の宣言を含む構造体のインスタンスの型を示します。The following rules apply to unary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:

  • 単項+-!、または~演算子は、型の 1 つのパラメーターを受け取る必要がありますTまたはT?任意の型を返すことができます。A unary +, -, !, or ~ operator must take a single parameter of type T or T? and can return any type.
  • 単項++または--演算子は、型の 1 つのパラメーターを受け取る必要がありますTまたはT?から同じ型または型が派生を返す必要があります。A unary ++ or -- operator must take a single parameter of type T or T? and must return that same type or a type derived from it.
  • 単項trueまたはfalse演算子は、型の 1 つのパラメーターを受け取る必要がありますTまたはT?と型を返す必要がありますboolします。A unary true or false operator must take a single parameter of type T or T? and must return type bool.

単項演算子のシグネチャは、演算子のトークンで構成されます (+-!~++--true、またはfalse) と 1 つの仮パラメーターの型。The signature of a unary operator consists of the operator token (+, -, !, ~, ++, --, true, or false) and the type of the single formal parameter. 戻り値の型は、単項演算子のシグネチャの一部でないも仮パラメーターの名前を指定します。The return type is not part of a unary operator's signature, nor is the name of the formal parameter.

truefalse単項演算子には、ペアで宣言が必要があります。The true and false unary operators require pair-wise declaration. クラスがこれらの演算子の 1 つも、もう一方を宣言せずに宣言する場合、コンパイル時エラーが発生します。A compile-time error occurs if a class declares one of these operators without also declaring the other. truefalse演算子の詳細についてはユーザー定義の条件付き論理演算子ブール式します。The true and false operators are described further in User-defined conditional logical operators and Boolean expressions.

次の例では、実装とのそれ以降の使用を示しています。operator ++整数ベクター クラス。The following example shows an implementation and subsequent usage of operator ++ for an integer vector class:

public class IntVector
{
    public IntVector(int length) {...}

    public int Length {...}                 // read-only property

    public int this[int index] {...}        // read-write indexer

    public static IntVector operator ++(IntVector iv) {
        IntVector temp = new IntVector(iv.Length);
        for (int i = 0; i < iv.Length; i++)
            temp[i] = iv[i] + 1;
        return temp;
    }
}

class Test
{
    static void Main() {
        IntVector iv1 = new IntVector(4);    // vector of 4 x 0
        IntVector iv2;

        iv2 = iv1++;    // iv2 contains 4 x 0, iv1 contains 4 x 1
        iv2 = ++iv1;    // iv2 contains 4 x 2, iv1 contains 4 x 2
    }
}

演算子のメソッドが後置インクリメントと同じように、オペランドに 1 を追加することによって生成された値を返す方法に注意してくださいし、前置デクリメント演算子 (置インクリメント演算子と前置デクリメント演算子)、前置インクリメントとデクリメント演算子 (前置インクリメントとデクリメント演算子)。Note how the operator method returns the value produced by adding 1 to the operand, just like the postfix increment and decrement operators (Postfix increment and decrement operators), and the prefix increment and decrement operators (Prefix increment and decrement operators). 異なり C++ では、このメソッド必要がありますいない、オペランドの値を直接変更します。Unlike in C++, this method need not modify the value of its operand directly. 実際には、オペランドの値を変更すると、後置のインクリメント演算子の標準のセマンティクスが違反していました。In fact, modifying the operand value would violate the standard semantics of the postfix increment operator.

バイナリ演算子Binary operators

二項演算子の宣言に、次の規則が適用されます、Tはクラスまたは演算子の宣言を含む構造体のインスタンスの型を示します。The following rules apply to binary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:

  • バイナリの非シフト演算子は、型である必要がありますが少なくとも 1 つ、2 つのパラメーターを受け取る必要がありますTまたはT?、任意の型を返すことができます。A binary non-shift operator must take two parameters, at least one of which must have type T or T?, and can return any type.
  • バイナリ<<または>>演算子の型である必要があります、2 つのパラメーターを受け取る必要がありますTまたはT?2 番目の型である必要がありますとintまたはint?、任意の型を返すことができます。A binary << or >> operator must take two parameters, the first of which must have type T or T? and the second of which must have type int or int?, and can return any type.

二項演算子のシグネチャは、演算子のトークンで構成されます (+-*/%&|^<<>>==!=><>=、または<=) と 2 つの仮パラメーターの型。The signature of a binary operator consists of the operator token (+, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, or <=) and the types of the two formal parameters. 戻り値の型と仮パラメーターの名前は、二項演算子のシグネチャの一部ではありません。The return type and the names of the formal parameters are not part of a binary operator's signature.

特定のバイナリ演算子では、ペアで宣言が必要です。Certain binary operators require pair-wise declaration. すべてのペアのいずれかの演算子の宣言では、ペアの他の演算子の宣言に一致する必要があります。For every declaration of either operator of a pair, there must be a matching declaration of the other operator of the pair. 2 つの演算子の宣言は同じ戻り値の型と各パラメーターの型が同じである場合と一致します。Two operator declarations match when they have the same return type and the same type for each parameter. 次の演算子には、ペアで宣言が必要です。The following operators require pair-wise declaration:

  • operator == および operator !=operator == and operator !=
  • operator > および operator <operator > and operator <
  • operator >= および operator <=operator >= and operator <=

変換演算子Conversion operators

変換演算子の宣言が導入されています、ユーザー定義の変換(ユーザー定義の変換) 定義済みの明示的および暗黙的な変換を強化します。A conversion operator declaration introduces a user-defined conversion (User-defined conversions) which augments the pre-defined implicit and explicit conversions.

変換演算子の宣言を含む、implicitキーワードには、ユーザー定義の暗黙的な変換が導入されています。A conversion operator declaration that includes the implicit keyword introduces a user-defined implicit conversion. 暗黙的な変換は、さまざまな関数メンバーの呼び出し、式のキャスト、代入などの状況で発生することができます。Implicit conversions can occur in a variety of situations, including function member invocations, cast expressions, and assignments. 詳細についてはこの暗黙的な変換します。This is described further in Implicit conversions.

変換演算子の宣言を含む、explicitキーワードには、ユーザー定義の明示的な変換が導入されています。A conversion operator declaration that includes the explicit keyword introduces a user-defined explicit conversion. 明示的な変換は、キャスト式で発生しの詳細については明示的な変換します。Explicit conversions can occur in cast expressions, and are described further in Explicit conversions.

変換演算子は、戻り値の型変換演算子によって示される、ターゲットの型に、変換演算子のパラメーターの型によって示される、ソースの種類からに変換します。A conversion operator converts from a source type, indicated by the parameter type of the conversion operator, to a target type, indicated by the return type of the conversion operator.

指定したソースの種類Sターゲットの種類とT場合は、SまたはTは null 許容型は、ようにS0T0それ以外の場合、基になる型を参照してくださいS0T0は等しいSTそれぞれします。For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. ソースの種類からの変換を宣言するクラスまたは構造体が許可されているSをターゲットの型T次のすべてに当てはまる場合にのみ。A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:

  • S0 T0はさまざまな種類。S0 and T0 are different types.
  • いずれかS0またはT0演算子宣言が行われるクラスまたは構造体の型です。Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • どちらもS0T0は、 interface_typeします。Neither S0 nor T0 is an interface_type.
  • ユーザー定義の変換を除く、変換が存在しないからSTまたはからTSします。Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

これらの規則のためには、任意の型パラメーターに関連付けられているSまたはTが、他の種類、継承関係とパラメーターが無視されるこれらの型に対する制約のない一意の型と見なされます。For the purposes of these rules, any type parameters associated with S or T are considered to be unique types that have no inheritance relationship with other types, and any constraints on those type parameters are ignored.

In the example

class C<T> {...}

class D<T>: C<T>
{
    public static implicit operator C<int>(D<T> value) {...}      // Ok
    public static implicit operator C<string>(D<T> value) {...}   // Ok
    public static implicit operator C<T>(D<T> value) {...}        // Error
}

最初の 2 つの演算子の宣言は許可のためインデクサー.3Tintstringそれぞれ一意の型とは関係がないと見なされます。the first two operator declarations are permitted because, for the purposes of Indexers.3, T and int and string respectively are considered unique types with no relationship. しかし、3 番目の演算子がエラーC<T>の基本クラスは、D<T>します。However, the third operator is an error because C<T> is the base class of D<T>.

2 番目のルールに従っている変換演算子は、または演算子が宣言されているクラスまたは構造体の型から変換する必要があります。From the second rule it follows that a conversion operator must convert either to or from the class or struct type in which the operator is declared. たとえば、クラスまたは構造体の型はCから変換を定義するCintとの間intCがからではなくintboolします。For example, it is possible for a class or struct type C to define a conversion from C to int and from int to C, but not from int to bool.

定義済みの変換を直接再定義することはできません。It is not possible to directly redefine a pre-defined conversion. したがって、変換演算子がからまたは変換を許可されていませんobject間明示的および暗黙的な変換が既に存在するためobjectおよびその他のすべての型。Thus, conversion operators are not allowed to convert from or to object because implicit and explicit conversions already exist between object and all other types. 同様に、ソースでも、変換のターゲットの種類できます、その他の基本型変換は既に存在しため。Likewise, neither the source nor the target types of a conversion can be a base type of the other, since a conversion would then already exist.

ただし、特定の型引数の定義済みの変換として既に存在する変換を指定するジェネリック型で演算子を宣言することはできます。However, it is possible to declare operators on generic types that, for particular type arguments, specify conversions that already exist as pre-defined conversions. In the example

struct Convertible<T>
{
    public static implicit operator Convertible<T>(T value) {...}
    public static explicit operator T(Convertible<T> value) {...}
}

入力するとobjectがの型引数として指定されてT、2 番目の演算子が既に存在する変換を宣言します (、暗黙的なため明示的でも任意の型を型から変換が存在するobject)。when type object is specified as a type argument for T, the second operator declares a conversion that already exists (an implicit, and therefore also an explicit, conversion exists from any type to type object).

2 種類の定義済みの変換が存在する場合、それらの型の間でユーザー定義の変換は無視されます。In cases where a pre-defined conversion exists between two types, any user-defined conversions between those types are ignored. 具体的には、次のように使用します。Specifically:

  • 場合、定義済みの暗黙的な変換 (暗黙的な変換) 型からが存在するS入力T、すべてのユーザー定義の変換 (暗黙的または明示的な) からSTは無視されます。If a pre-defined implicit conversion (Implicit conversions) exists from type S to type T, all user-defined conversions (implicit or explicit) from S to T are ignored.
  • 定義済みの明示的な変換の場合 (明示的な変換) 型から存在するS入力T、ユーザーによる明示的な変換からSTは無視されます。If a pre-defined explicit conversion (Explicit conversions) exists from type S to type T, any user-defined explicit conversions from S to T are ignored. さらには。Furthermore:

場合Tインターフェイス型は、ユーザー定義からの暗黙的な変換は、STは無視されます。If T is an interface type, user-defined implicit conversions from S to T are ignored.

それ以外の場合、ユーザー定義の暗黙的な変換からSTと見なされます。Otherwise, user-defined implicit conversions from S to T are still considered.

すべての種類がobject、によって演算子が宣言されている、Convertible<T>上記の型が定義済みの変換と競合しません。For all types but object, the operators declared by the Convertible<T> type above do not conflict with pre-defined conversions. 例:For example:

void F(int i, Convertible<int> n) {
    i = n;                          // Error
    i = (int)n;                     // User-defined explicit conversion
    n = i;                          // User-defined implicit conversion
    n = (Convertible<int>)i;        // User-defined implicit conversion
}

ただし、型のobject、定義済みの変換には、すべてのケースが 1 つのユーザー定義の変換が非表示にします。However, for type object, pre-defined conversions hide the user-defined conversions in all cases but one:

void F(object o, Convertible<object> n) {
    o = n;                         // Pre-defined boxing conversion
    o = (object)n;                 // Pre-defined boxing conversion
    n = o;                         // User-defined implicit conversion
    n = (Convertible<object>)o;    // Pre-defined unboxing conversion
}

ユーザー定義の変換からの変換は許可されませんinterface_type秒。User-defined conversions are not allowed to convert from or to interface_types. 具体的には、この制限により、ユーザー定義の変換が発生しないことに変換するときに、 interface_type、ことへの変換、 interface_type場合にのみ成功オブジェクト実際に変換される、指定した実装interface_typeします。In particular, this restriction ensures that no user-defined transformations occur when converting to an interface_type, and that a conversion to an interface_type succeeds only if the object being converted actually implements the specified interface_type.

変換演算子のシグネチャは、ソースの種類とターゲットの種類で構成されます。The signature of a conversion operator consists of the source type and the target type. (対象の戻り値の型は、署名に参加しているメンバーの唯一の形式であるに注意してください)。implicitまたはexplicit変換演算子の分類が演算子のシグネチャの一部ではありません。(Note that this is the only form of member for which the return type participates in the signature.) The implicit or explicit classification of a conversion operator is not part of the operator's signature. したがって、クラスまたは構造体を宣言できません両方、implicitexplicitを同じソースとターゲットの型変換演算子。Thus, a class or struct cannot declare both an implicit and an explicit conversion operator with the same source and target types.

一般に、ユーザー定義の暗黙的な変換は例外をスローしないと、情報が失われることはありませんするように設計する必要があります。In general, user-defined implicit conversions should be designed to never throw exceptions and never lose information. ユーザー定義の変換は、(たとえば、元の引数が範囲外です) ために、例外の上昇を与えることが場合はその変換 (上位ビットが破棄) などの情報の損失は、明示的な変換として定義する必要があります。If a user-defined conversion can give rise to exceptions (for example, because the source argument is out of range) or loss of information (such as discarding high-order bits), then that conversion should be defined as an explicit conversion.

In the example

using System;

public struct Digit
{
    byte value;

    public Digit(byte value) {
        if (value < 0 || value > 9) throw new ArgumentException();
        this.value = value;
    }

    public static implicit operator byte(Digit d) {
        return d.value;
    }

    public static explicit operator Digit(byte b) {
        return new Digit(b);
    }
}

変換Digitbyte決してに例外がスローまたはについてがからの変換を失うので、暗黙的にbyteDigit以降明示的Digitの使用可能なサブセットを表すことができますのみ値をbyteします。the conversion from Digit to byte is implicit because it never throws exceptions or loses information, but the conversion from byte to Digit is explicit since Digit can only represent a subset of the possible values of a byte.

インスタンス コンス トラクターInstance constructors

"インスタンス コンストラクター" は、クラスのインスタンスを初期化するために必要なアクションを実装するメンバーです。An instance constructor is a member that implements the actions required to initialize an instance of a class. 使用してインスタンス コンス トラクターが宣言されたconstructor_declaration: %sInstance constructors are declared using constructor_declarations:

constructor_declaration
    : attributes? constructor_modifier* constructor_declarator constructor_body
    ;

constructor_modifier
    : 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'extern'
    | constructor_modifier_unsafe
    ;

constructor_declarator
    : identifier '(' formal_parameter_list? ')' constructor_initializer?
    ;

constructor_initializer
    : ':' 'base' '(' argument_list? ')'
    | ':' 'this' '(' argument_list? ')'
    ;

constructor_body
    : block
    | ';'
    ;

A constructor_declarationのセットを含めることができます属性(属性)、有効な 4 つのアクセス修飾子の組み合わせ (アクセス修飾子)、およびextern(外部メソッド) 修飾子。A constructor_declaration may include a set of attributes (Attributes), a valid combination of the four access modifiers (Access modifiers), and an extern (External methods) modifier. 複数回、同じ修飾子を含めるには、コンス トラクターの宣言は許可されていません。A constructor declaration is not permitted to include the same modifier multiple times.

識別子constructor_declaratorインスタンス コンス トラクターが宣言されているクラスの名前を指定する必要があります。The identifier of a constructor_declarator must name the class in which the instance constructor is declared. その他の任意の名前を指定すると、コンパイル時エラーが発生します。If any other name is specified, a compile-time error occurs.

省略可能なformal_parameter_listインスタンスのコンス トラクターと同じ規則に従って、 formal_parameter_listメソッドの (メソッド)。The optional formal_parameter_list of an instance constructor is subject to the same rules as the formal_parameter_list of a method (Methods). 仮パラメーター リストは、署名を定義します (シグネチャとオーバー ロード)、インスタンス コンス トラクターのというプロセスを管理オーバー ロードの解決 (型推論) 特定の選択呼び出しのインスタンス コンス トラクターです。The formal parameter list defines the signature (Signatures and overloading) of an instance constructor and governs the process whereby overload resolution (Type inference) selects a particular instance constructor in an invocation.

参照される型の各、 formal_parameter_listインスタンスのコンス トラクターは、少なくともコンス トラクター自体と同程度にアクセスする必要があります (アクセシビリティ制約)。Each of the types referenced in the formal_parameter_list of an instance constructor must be at least as accessible as the constructor itself (Accessibility constraints).

省略可能なconstructor_initializerで指定されたステートメントを実行する前に呼び出すための別のインスタンス コンス トラクターを指定します、 constructor_bodyのこのインスタンスのコンス トラクター。The optional constructor_initializer specifies another instance constructor to invoke before executing the statements given in the constructor_body of this instance constructor. 詳細についてはこのコンス トラクター初期化子します。This is described further in Constructor initializers.

コンス トラクターの宣言が含まれています、extern修飾子は、コンス トラクターはモード、コンス トラクターの外部します。When a constructor declaration includes an extern modifier, the constructor is said to be an external constructor. 外部コンス トラクターの宣言は、実際の実装を提供しないため、そのconstructor_bodyをセミコロンで構成されます。Because an external constructor declaration provides no actual implementation, its constructor_body consists of a semicolon. その他のすべてのコンス トラクター、 constructor_bodyから成る、ブロッククラスの新しいインスタンスを初期化するステートメントを指定します。For all other constructors, the constructor_body consists of a block which specifies the statements to initialize a new instance of the class. これは正確に対応して、ブロックを持つインスタンス メソッドのvoid型を返す (メソッド本体)。This corresponds exactly to the block of an instance method with a void return type (Method body).

インスタンス コンス トラクターは継承されません。Instance constructors are not inherited. したがって、クラスでは、実際には、クラスで宣言されている以外のインスタンス コンス トラクターがありません。Thus, a class has no instance constructors other than those actually declared in the class. 既定のインスタンス コンス トラクターが自動的に提供されるクラスにインスタンス コンス トラクターの宣言が含まれていない場合 (既定のコンス トラクター)。If a class contains no instance constructor declarations, a default instance constructor is automatically provided (Default constructors).

インスタンス コンス トラクターを呼び出すobject_creation_expressions (オブジェクト作成式) および ~ constructor_initializer秒。Instance constructors are invoked by object_creation_expressions (Object creation expressions) and through constructor_initializers.

Constructor Initializers (コンストラクター初期化子)Constructor initializers

すべてのインスタンス コンス トラクター (クラスを除く、 object) 暗黙的に別のインスタンス コンス トラクターの呼び出しをする直前に含める、 constructor_bodyします。All instance constructors (except those for class object) implicitly include an invocation of another instance constructor immediately before the constructor_body. 暗黙的に呼び出すコンス トラクターはによって決定されます、 constructor_initializer:The constructor to implicitly invoke is determined by the constructor_initializer:

  • フォームのインスタンス コンス トラクター初期化子base(argument_list)またはbase()により呼び出される直接の基本クラスからインスタンス コンス トラクター。An instance constructor initializer of the form base(argument_list) or base() causes an instance constructor from the direct base class to be invoked. 使用してそのコンス トラクターを選択argument_list場合存在し、オーバー ロード解決規則オーバー ロードの解決します。That constructor is selected using argument_list if present and the overload resolution rules of Overload resolution. 直接の基本クラスに含まれているすべてのアクセス可能なインスタンス コンス トラクターまたは既定のコンス トラクターの候補のインスタンス コンス トラクターのセットで構成されます (既定のコンス トラクター) にインスタンス コンス トラクターが宣言されていない場合、直接の基本クラスです。The set of candidate instance constructors consists of all accessible instance constructors contained in the direct base class, or the default constructor (Default constructors), if no instance constructors are declared in the direct base class. このセットが空の場合、または 1 つの最適なインスタンス コンス トラクターを識別できない場合は、コンパイル時エラーが発生します。If this set is empty, or if a single best instance constructor cannot be identified, a compile-time error occurs.
  • フォームのインスタンス コンス トラクター初期化子this(argument-list)またはthis()自体を呼び出すクラスのインスタンス コンス トラクターを発生します。An instance constructor initializer of the form this(argument-list) or this() causes an instance constructor from the class itself to be invoked. 使用して、コンス トラクターを選択argument_list場合存在し、オーバー ロード解決規則オーバー ロードの解決します。The constructor is selected using argument_list if present and the overload resolution rules of Overload resolution. インスタンス コンス トラクターの候補のセットは、クラス自体で宣言されているすべてのアクセス可能なインスタンス コンス トラクターで構成されます。The set of candidate instance constructors consists of all accessible instance constructors declared in the class itself. このセットが空の場合、または 1 つの最適なインスタンス コンス トラクターを識別できない場合は、コンパイル時エラーが発生します。If this set is empty, or if a single best instance constructor cannot be identified, a compile-time error occurs. インスタンス コンス トラクターの宣言には、コンス トラクター自体を呼び出すコンス トラクター初期化子が含まれている場合、コンパイル時エラーが発生します。If an instance constructor declaration includes a constructor initializer that invokes the constructor itself, a compile-time error occurs.

インスタンス コンス トラクターは、フォームのコンス トラクター初期化子、コンス トラクター初期化子を持たない場合base()が暗黙的に指定します。If an instance constructor has no constructor initializer, a constructor initializer of the form base() is implicitly provided. したがって、インスタンス コンス トラクターの宣言フォームのThus, an instance constructor declaration of the form

C(...) {...}

まったく同じです。is exactly equivalent to

C(...): base() {...}

によって指定されたパラメーターのスコープ、 formal_parameter_list宣言には、インスタンス コンス トラクターの宣言のコンス トラクター初期化子が含まれています。The scope of the parameters given by the formal_parameter_list of an instance constructor declaration includes the constructor initializer of that declaration. そのため、コンス トラクター初期化子はコンス トラクターのパラメーターにアクセスを許可します。Thus, a constructor initializer is permitted to access the parameters of the constructor. 例:For example:

class A
{
    public A(int x, int y) {}
}

class B: A
{
    public B(int x, int y): base(x + y, x - y) {}
}

インスタンス コンス トラクターの初期化子は、作成中のインスタンスにアクセスできません。An instance constructor initializer cannot access the instance being created. そのため、コンパイル時のエラーを参照するがthisコンス トラクター初期化子の引数式、としては、による任意のインスタンス メンバーを参照する引数式のコンパイル時エラー、 simple_name.Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple_name.

インスタンス変数初期化子Instance variable initializers

インスタンス コンス トラクターを持たないコンス トラクター初期化子、またはフォームのコンス トラクター初期化子があるとbase(...)、そのコンス トラクターが暗黙的に指定された初期化を実行、 variable_initializerの sインスタンス フィールドは、そのクラスで宣言します。When an instance constructor has no constructor initializer, or it has a constructor initializer of the form base(...), that constructor implicitly performs the initializations specified by the variable_initializers of the instance fields declared in its class. これは、一連のコンス トラクターに、直接基底クラスのコンス トラクターの暗黙的な呼び出しの前に入ったときにすぐに実行される割り当てに対応します。This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor. 変数の初期化子は、クラス宣言に表示されるテキストの順序で実行されます。The variable initializers are executed in the textual order in which they appear in the class declaration.

コンス トラクターの実行Constructor execution

変数初期化子は代入ステートメントに変換され、基底クラスのインスタンス コンス トラクターの呼び出しの前にこれらの代入ステートメントが実行されます。Variable initializers are transformed into assignment statements, and these assignment statements are executed before the invocation of the base class instance constructor. この順序により、すべてのインスタンス フィールドは、そのインスタンスへのアクセス権を持つすべてのステートメントが実行される前に、変数初期化子で初期化されます。This ordering ensures that all instance fields are initialized by their variable initializers before any statements that have access to that instance are executed.

例を示しますGiven the example

using System;

class A
{
    public A() {
        PrintFields();
    }

    public virtual void PrintFields() {}
}

class B: A
{
    int x = 1;
    int y;

    public B() {
        y = -1;
    }

    public override void PrintFields() {
        Console.WriteLine("x = {0}, y = {1}", x, y);
    }
}

ときにnew B()のインスタンスを作成するために使用B、次の出力が生成されます。when new B() is used to create an instance of B, the following output is produced:

x = 1, y = 0

x1 は、基底クラスのインスタンス コンス トラクターが呼び出される前に、変数の初期化子が実行されるためです。The value of x is 1 because the variable initializer is executed before the base class instance constructor is invoked. ただしの値yは 0 です (既定値のint) ためへの割り当てをy基底クラスのコンス トラクターから制御が戻た後までは実行されません。However, the value of y is 0 (the default value of an int) because the assignment to y is not executed until after the base class constructor returns.

インスタンス変数初期化子とコンス トラクター初期化子、ステートメントの前に自動的に挿入されると考えると便利だと、 constructor_bodyします。It is useful to think of instance variable initializers and constructor initializers as statements that are automatically inserted before the constructor_body. 例では、The example

using System;
using System.Collections;

class A
{
    int x = 1, y = -1, count;

    public A() {
        count = 0;
    }

    public A(int n) {
        count = n;
    }
}

class B: A
{
    double sqrt2 = Math.Sqrt(2.0);
    ArrayList items = new ArrayList(100);
    int max;

    public B(): this(100) {
        items.Add("default");
    }

    public B(int n): base(n - 1) {
        max = n;
    }
}

いくつかの変数初期化子; が含まれています両方のフォームのコンス トラクター初期化子も含まれています (basethis)。contains several variable initializers; it also contains constructor initializers of both forms (base and this). 例は、次のコードに対応が各コメントが (自動的に挿入されたコンス トラクターの呼び出しに使用する構文が有効でないが、メカニズムを説明するためにのみ機能します)、自動的に挿入されたステートメントを示します。The example corresponds to the code shown below, where each comment indicates an automatically inserted statement (the syntax used for the automatically inserted constructor invocations isn't valid, but merely serves to illustrate the mechanism).

using System.Collections;

class A
{
    int x, y, count;

    public A() {
        x = 1;                       // Variable initializer
        y = -1;                      // Variable initializer
        object();                    // Invoke object() constructor
        count = 0;
    }

    public A(int n) {
        x = 1;                       // Variable initializer
        y = -1;                      // Variable initializer
        object();                    // Invoke object() constructor
        count = n;
    }
}

class B: A
{
    double sqrt2;
    ArrayList items;
    int max;

    public B(): this(100) {
        B(100);                      // Invoke B(int) constructor
        items.Add("default");
    }

    public B(int n): base(n - 1) {
        sqrt2 = Math.Sqrt(2.0);      // Variable initializer
        items = new ArrayList(100);  // Variable initializer
        A(n - 1);                    // Invoke A(int) constructor
        max = n;
    }
}

既定のコンストラクターDefault constructors

クラスにインスタンス コンス トラクターの宣言が含まれていない場合は、既定のインスタンス コンス トラクターが自動的に提供します。If a class contains no instance constructor declarations, a default instance constructor is automatically provided. 既定のコンス トラクターは、直接基底クラスのパラメーターなしのコンス トラクターを呼び出すだけです。That default constructor simply invokes the parameterless constructor of the direct base class. 抽象クラスで宣言されたアクセシビリティの既定のコンス トラクターは保護されています。If the class is abstract then the declared accessibility for the default constructor is protected. それ以外の場合、既定のコンス トラクターの宣言されたアクセシビリティがパブリックです。Otherwise, the declared accessibility for the default constructor is public. したがって、既定のコンス トラクターは常にフォームのThus, the default constructor is always of the form

protected C(): base() {}

またはor

public C(): base() {}

場所Cクラスの名前を指定します。where C is the name of the class. オーバー ロードの解決が基底クラスのコンス トラクター初期化子に一意の最適な候補を特定できない場合は、コンパイル時エラーが発生します。If overload resolution is unable to determine a unique best candidate for the base class constructor initializer then a compile-time error occurs.

In the example

class Message
{
    object sender;
    string text;
}

クラスにインスタンス コンス トラクターの宣言が含まれていないために、既定のコンス トラクターが提供されます。a default constructor is provided because the class contains no instance constructor declarations. したがって、例では、とまったく同じです。Thus, the example is precisely equivalent to

class Message
{
    object sender;
    string text;

    public Message(): base() {}
}

プライベート コンス トラクターPrivate constructors

クラスとTプライベート インスタンス コンス トラクターのみを宣言して、プログラム テキストの外側のクラスのことはできませんTから派生するTまたは直接のインスタンスを作成するTします。When a class T declares only private instance constructors, it is not possible for classes outside the program text of T to derive from T or to directly create instances of T. したがって、クラスが静的メンバーのみが含まれています、インスタンス化するためのものでない場合、空のプライベート インスタンス コンス トラクターを追加することはインスタンス化されないようにします。Thus, if a class contains only static members and isn't intended to be instantiated, adding an empty private instance constructor will prevent instantiation. 例:For example:

public class Trig
{
    private Trig() {}        // Prevent instantiation

    public const double PI = 3.14159265358979323846;

    public static double Sin(double x) {...}
    public static double Cos(double x) {...}
    public static double Tan(double x) {...}
}

Trigクラスは、関連するメソッドと定数、グループが、インスタンス化するものではありません。The Trig class groups related methods and constants, but is not intended to be instantiated. そのため、1 つの空のプライベート インスタンス コンス トラクターを宣言します。Therefore it declares a single empty private instance constructor. 既定のコンス トラクターの自動生成を抑制するには、少なくとも 1 つのインスタンス コンス トラクターを宣言しなければなりません。At least one instance constructor must be declared to suppress the automatic generation of a default constructor.

省略可能なインスタンス コンス トラクターのパラメーターOptional instance constructor parameters

this(...)オプションのインスタンス コンス トラクターのパラメーターを実装するために、コンス トラクター初期化子の形式はオーバー ロードと組み合わせて使用一般的です。The this(...) form of constructor initializer is commonly used in conjunction with overloading to implement optional instance constructor parameters. In the example

class Text
{
    public Text(): this(0, 0, null) {}

    public Text(int x, int y): this(x, y, null) {}

    public Text(int x, int y, string s) {
        // Actual constructor implementation
    }
}

最初の 2 つのインスタンス コンス トラクターは、だけで欠けている引数の既定値を指定します。the first two instance constructors merely provide the default values for the missing arguments. 両方を使用して、this(...)を 3 つ目の新しいインスタンスを初期化中のインスタンス コンス トラクターを呼び出すコンス トラクター初期化子。Both use a this(...) constructor initializer to invoke the third instance constructor, which actually does the work of initializing the new instance. 省略可能なコンス トラクターのパラメーターの意味になります。The effect is that of optional constructor parameters:

Text t1 = new Text();                    // Same as Text(0, 0, null)
Text t2 = new Text(5, 10);               // Same as Text(5, 10, null)
Text t3 = new Text(5, 20, "Hello");

静的コンストラクターStatic constructors

A静的コンス トラクターが閉じられたクラス型の初期化に必要なアクションを実装するメンバー。A static constructor is a member that implements the actions required to initialize a closed class type. 使用して静的コンス トラクターが宣言されたstatic_constructor_declaration: %sStatic constructors are declared using static_constructor_declarations:

static_constructor_declaration
    : attributes? static_constructor_modifiers identifier '(' ')' static_constructor_body
    ;

static_constructor_modifiers
    : 'extern'? 'static'
    | 'static' 'extern'?
    | static_constructor_modifiers_unsafe
    ;

static_constructor_body
    : block
    | ';'
    ;

A static_constructor_declarationのセットを含めることができます属性(属性) およびextern修飾子 (の外部メソッド).A static_constructor_declaration may include a set of attributes (Attributes) and an extern modifier (External methods).

識別子static_constructor_declaration静的コンス トラクターが宣言されているクラスの名前を指定する必要があります。The identifier of a static_constructor_declaration must name the class in which the static constructor is declared. その他の任意の名前を指定すると、コンパイル時エラーが発生します。If any other name is specified, a compile-time error occurs.

静的コンス トラクターの宣言が含まれています、extern修飾子は、静的コンス トラクターはモード、外部の静的コンス トラクターします。When a static constructor declaration includes an extern modifier, the static constructor is said to be an external static constructor. 外部の静的コンス トラクターの宣言は、実際の実装を提供しないため、そのstatic_constructor_bodyをセミコロンで構成されます。Because an external static constructor declaration provides no actual implementation, its static_constructor_body consists of a semicolon. その他のすべての静的コンス トラクター宣言、 static_constructor_bodyから成る、ブロッククラスを初期化するために実行するステートメントを指定します。For all other static constructor declarations, the static_constructor_body consists of a block which specifies the statements to execute in order to initialize the class. これには対応、 method_bodyして静的メソッドのvoid型を返す (メソッド本体)。This corresponds exactly to the method_body of a static method with a void return type (Method body).

静的コンス トラクターは継承されませんし、直接呼び出すことはできません。Static constructors are not inherited, and cannot be called directly.

閉じられたクラス型の静的コンス トラクターは、特定のアプリケーション ドメインで最大で 1 回実行します。The static constructor for a closed class type executes at most once in a given application domain. 静的コンス トラクターの実行は、次のイベントの最初のアプリケーション ドメイン内に発生するによってトリガーされます。The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • クラス型のインスタンスが作成されます。An instance of the class type is created.
  • クラス型の静的メンバーのいずれかが参照されます。Any of the static members of the class type are referenced.

クラスが含まれている場合、Mainメソッド (アプリケーションの起動) で、どの実行が開始される、静的コンス トラクターの前にそのクラスが実行される、Mainメソッドが呼び出されます。If a class contains the Main method (Application Startup) in which execution begins, the static constructor for that class executes before the Main method is called.

最初の静的フィールドの新しいセットで閉じられたクラスの新しい型を初期化するために (静的およびインスタンス フィールド) 特定のクローズ型を作成します。To initialize a new closed class type, first a new set of static fields (Static and instance fields) for that particular closed type is created. 静的フィールドの各はその既定値に初期化 (既定値)。Each of the static fields is initialized to its default value (Default values). 次に、静的フィールド初期化子 (静的フィールドの初期化) それらの静的フィールドが実行されます。Next, the static field initializers (Static field initialization) are executed for those static fields. 最後に、静的コンス トラクターが実行されます。Finally, the static constructor is executed.

例では、The example

using System;

class Test
{
    static void Main() {
        A.F();
        B.F();
    }
}

class A
{
    static A() {
        Console.WriteLine("Init A");
    }
    public static void F() {
        Console.WriteLine("A.F");
    }
}

class B
{
    static B() {
        Console.WriteLine("Init B");
    }
    public static void F() {
        Console.WriteLine("B.F");
    }
}

出力を生成する必要があります。must produce the output:

Init A
A.F
Init B
B.F

の実行Aの静的コンス トラクターがへの呼び出しによってトリガーされるA.Fの実行とBの静的コンス トラクターがへの呼び出しによってトリガーされるB.Fします。because the execution of A's static constructor is triggered by the call to A.F, and the execution of B's static constructor is triggered by the call to B.F.

既定値の状態で見られる変数初期化子を含む静的フィールドの循環依存関係を構築することになります。It is possible to construct circular dependencies that allow static fields with variable initializers to be observed in their default value state.

例では、The example

using System;

class A
{
    public static int X;

    static A() {
        X = B.Y + 1;
    }
}

class B
{
    public static int Y = A.X + 1;

    static B() {}

    static void Main() {
        Console.WriteLine("X = {0}, Y = {1}", A.X, B.Y);
    }
}

この例では、次のように出力されます。produces the output

X = 1, Y = 2

実行する、Mainメソッドをシステムを初めて実行の初期化子B.Yクラスを前に、Bの静的コンス トラクター。To execute the Main method, the system first runs the initializer for B.Y, prior to class B's static constructor. Y初期化子によってAのために実行する静的コンス トラクターの値A.X参照されます。Y's initializer causes A's static constructor to be run because the value of A.X is referenced. 静的コンス トラクター Aの値を計算に続いて Xの既定値はフェッチそうすることで Yゼロであります。The static constructor of A in turn proceeds to compute the value of X, and in doing so fetches the default value of Y, which is zero. A.X そのため 1 に初期化されます。A.X is thus initialized to 1. 実行中のプロセスA静的フィールド初期化子と静的コンス トラクターの後が完了したらの初期値の計算に返す Yこれは 2 となります。The process of running A's static field initializers and static constructor then completes, returning to the calculation of the initial value of Y, the result of which becomes 2.

実行時のチェック制約を使用してコンパイル時にチェックすることはできませんが、型パラメーターに適用する便利な場所は、静的コンス トラクターは、それぞれのクローズ構築されたクラス型の 1 回だけ実行は、ため、(型パラメーター制約)。Because the static constructor is executed exactly once for each closed constructed class type, it is a convenient place to enforce run-time checks on the type parameter that cannot be checked at compile-time via constraints (Type parameter constraints). たとえば、次の種類は、型引数が列挙型を強制するのに静的コンス トラクターを使用します。For example, the following type uses a static constructor to enforce that the type argument is an enum:

class Gen<T> where T: struct
{
    static Gen() {
        if (!typeof(T).IsEnum) {
            throw new ArgumentException("T must be an enum");
        }
    }
}

デストラクターDestructors

Aデストラクターはクラスのインスタンスを消滅させるために必要なアクションを実装するメンバーです。A destructor is a member that implements the actions required to destruct an instance of a class. 使用して、デストラクターを宣言、 destructor_declaration:A destructor is declared using a destructor_declaration:

destructor_declaration
    : attributes? 'extern'? '~' identifier '(' ')' destructor_body
    | destructor_declaration_unsafe
    ;

destructor_body
    : block
    | ';'
    ;

A destructor_declarationのセットを含めることができます属性(属性)。A destructor_declaration may include a set of attributes (Attributes).

識別子destructor_declarationデストラクターが宣言されているクラスの名前を指定する必要があります。The identifier of a destructor_declaration must name the class in which the destructor is declared. その他の任意の名前を指定すると、コンパイル時エラーが発生します。If any other name is specified, a compile-time error occurs.

デストラクターの宣言が含まれています、extern修飾子は、デストラクターはモード、外部デストラクターします。When a destructor declaration includes an extern modifier, the destructor is said to be an external destructor. 外部デストラクターの宣言は、実際の実装を提供しないため、そのdestructor_bodyをセミコロンで構成されます。Because an external destructor declaration provides no actual implementation, its destructor_body consists of a semicolon. その他のすべてのデストラクターのdestructor_bodyから成る、ブロッククラスのインスタンスを破棄するために実行するステートメントを指定します。For all other destructors, the destructor_body consists of a block which specifies the statements to execute in order to destruct an instance of the class. A destructor_bodyに対応して、 method_bodyを持つインスタンス メソッドのvoid型を返す (メソッド本体)。A destructor_body corresponds exactly to the method_body of an instance method with a void return type (Method body).

デストラクターは継承されません。Destructors are not inherited. したがって、クラスでは、そのクラスで宣言されたもの以外のデストラクターがありません。Thus, a class has no destructors other than the one which may be declared in that class.

デストラクターは、パラメーターがない必要があることはできません、オーバー ロードされたクラスに参照できるように、最大で 1 つのデストラクター。Since a destructor is required to have no parameters, it cannot be overloaded, so a class can have, at most, one destructor.

デストラクターは、自動的に呼び出され、明示的に呼び出すことはできません。Destructors are invoked automatically, and cannot be invoked explicitly. インスタンスは、そのインスタンスを使用するには、どのコードが不要になったときに破壊の対象になります。An instance becomes eligible for destruction when it is no longer possible for any code to use that instance. インスタンスのデストラクターの実行のインスタンスが破壊の対象になると、いつでも発生します。Execution of the destructor for the instance may occur at any time after the instance becomes eligible for destruction. 順番に、そのインスタンスの継承チェーンでデストラクターが呼び出さインスタンスを破棄すると、ときにほとんどから派生する最低派生します。When an instance is destructed, the destructors in that instance's inheritance chain are called, in order, from most derived to least derived. デストラクターは、任意のスレッドで実行する場合があります。A destructor may be executed on any thread. タイミングとデストラクターの実行方法を制御するルールの詳細な説明については、次を参照してください。自動メモリ管理します。For further discussion of the rules that govern when and how a destructor is executed, see Automatic memory management.

この例の出力The output of the example

using System;

class A
{
    ~A() {
        Console.WriteLine("A's destructor");
    }
}

class B: A
{
    ~B() {
        Console.WriteLine("B's destructor");
    }
}

class Test
{
   static void Main() {
        B b = new B();
        b = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
   }
}

isis

B's destructor
A's destructor

デストラクターは、継承チェーンでは、順序で呼び出されるのでほとんどから派生する最低派生します。since destructors in an inheritance chain are called in order, from most derived to least derived.

デストラクターが仮想メソッドをオーバーライドすることによって実装されるFinalizeSystem.Objectします。Destructors are implemented by overriding the virtual method Finalize on System.Object. このメソッドをオーバーライドまたは (またはそのオーバーライド) を呼び出す c# プログラムは許可されていません直接します。C# programs are not permitted to override this method or call it (or overrides of it) directly. たとえば、プログラムFor instance, the program

class A 
{
    override protected void Finalize() {}    // error

    public void F() {
        this.Finalize();                     // error
    }
}

2 つのエラーが含まれています。contains two errors.

コンパイラは、このメソッドをおよび、上書きがまったく存在しないかのように動作します。The compiler behaves as if this method, and overrides of it, do not exist at all. したがって、このプログラム:Thus, this program:

class A 
{
    void Finalize() {}                            // permitted
}

有効で非表示になりますが、メソッドに示すように、System.ObjectFinalizeメソッド。is valid, and the method shown hides System.Object's Finalize method.

動作の詳細については、デストラクターから例外がスローされるを参照してください例外の処理方法します。For a discussion of the behavior when an exception is thrown from a destructor, see How exceptions are handled.

反復子Iterators

関数メンバー (関数メンバー) 反復子ブロックを使用して実装 (ブロック) と呼ばれますが、反復子します。A function member (Function members) implemented using an iterator block (Blocks) is called an iterator.

反復子ブロックは関数に対応するメンバーの戻り値の型は列挙子インターフェイスの 1 つとして、関数メンバーの本文として使用可能性があります (列挙子インターフェイス) または列挙可能なインターフェイスの 1 つ (列挙可能なインターフェイス)。An iterator block may be used as the body of a function member as long as the return type of the corresponding function member is one of the enumerator interfaces (Enumerator interfaces) or one of the enumerable interfaces (Enumerable interfaces). として発生する可能性が、 method_bodyoperator_bodyまたはaccessor_bodyイベント、インスタンス コンス トラクター、静的コンス トラクターおよびデストラクターがすることはできませんが、反復子として実装されます。It can occur as a method_body, operator_body or accessor_body, whereas events, instance constructors, static constructors and destructors cannot be implemented as iterators.

反復子ブロックを使用して関数のメンバーが実装されている場合は、いずれかを指定するメンバー関数の仮パラメーター リストのコンパイル時エラーrefまたはoutパラメーター。When a function member is implemented using an iterator block, it is a compile-time error for the formal parameter list of the function member to specify any ref or out parameters.

列挙子インターフェイスEnumerator interfaces

列挙子インターフェイス非ジェネリック インターフェイスはSystem.Collections.IEnumeratorジェネリック インターフェイスのすべてのインスタンス化とSystem.Collections.Generic.IEnumerator<T>します。The enumerator interfaces are the non-generic interface System.Collections.IEnumerator and all instantiations of the generic interface System.Collections.Generic.IEnumerator<T>. 説明を簡潔にするため、この章ではこれらのインターフェイスとして参照されますIEnumeratorIEnumerator<T>、それぞれします。For the sake of brevity, in this chapter these interfaces are referenced as IEnumerator and IEnumerator<T>, respectively.

列挙可能なインターフェイスEnumerable interfaces

列挙可能なインターフェイス非ジェネリック インターフェイスはSystem.Collections.IEnumerableジェネリック インターフェイスのすべてのインスタンス化とSystem.Collections.Generic.IEnumerable<T>します。The enumerable interfaces are the non-generic interface System.Collections.IEnumerable and all instantiations of the generic interface System.Collections.Generic.IEnumerable<T>. 説明を簡潔にするため、この章ではこれらのインターフェイスとして参照されますIEnumerableIEnumerable<T>、それぞれします。For the sake of brevity, in this chapter these interfaces are referenced as IEnumerable and IEnumerable<T>, respectively.

Yield 型Yield type

反復子は、すべて同じ型の値のシーケンスを生成します。An iterator produces a sequence of values, all of the same type. この型が呼び出される、型を生成の反復子。This type is called the yield type of the iterator.

  • 返す反復子の yield 型IEnumeratorまたはIEnumerableobjectします。The yield type of an iterator that returns IEnumerator or IEnumerable is object.
  • 返す反復子の yield 型IEnumerator<T>またはIEnumerable<T>Tします。The yield type of an iterator that returns IEnumerator<T> or IEnumerable<T> is T.

列挙子オブジェクトEnumerator objects

反復子ブロックを使用して列挙子インターフェイス型を返す関数のメンバーが実装されている関数メンバーを呼び出しても反復子ブロックのコードはすぐに実行されません。When a function member returning an enumerator interface type is implemented using an iterator block, invoking the function member does not immediately execute the code in the iterator block. 代わりに、列挙子オブジェクトが作成され、返されます。Instead, an enumerator object is created and returned. このオブジェクトは、反復子ブロックで指定されたコードをカプセル化し、反復子ブロック内のコードの実行時に、列挙子オブジェクトのMoveNextメソッドが呼び出されます。This object encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object's MoveNext method is invoked. 列挙子オブジェクトには、次の特徴があります。An enumerator object has the following characteristics:

  • 実装IEnumeratorIEnumerator<T>ここで、T反復子の yield 型です。It implements IEnumerator and IEnumerator<T>, where T is the yield type of the iterator.
  • このクラスは、System.IDisposable を実装します。It implements System.IDisposable.
  • 引数の値のコピーの初期化 (ある場合) および関数メンバーに渡されるインスタンスの値。It is initialized with a copy of the argument values (if any) and instance value passed to the function member.
  • 4 つの潜在的な状態がする前にを実行している中断、および、最初に、する前に状態。It has four potential states, before, running, suspended, and after, and is initially in the before state.

列挙子オブジェクトは、通常、反復子ブロック内のコードをカプセル化し、列挙子のインターフェイスを実装する列挙子のコンパイラによって生成されたクラスのインスタンスが他のメソッドの実装が可能です。An enumerator object is typically an instance of a compiler-generated enumerator class that encapsulates the code in the iterator block and implements the enumerator interfaces, but other methods of implementation are possible. 場合は、列挙子クラスは、コンパイラによって生成される、そのクラスは入れ子になった、直接的または間接的に、関数メンバーを含むクラスで private のアクセシビリティがおよびコンパイラを使用するために予約された名前になります (識別子).If an enumerator class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function member, it will have private accessibility, and it will have a name reserved for compiler use (Identifiers).

列挙子オブジェクトには、上記で指定したものより多くのインターフェイスを実装できます。An enumerator object may implement more interfaces than those specified above.

次のセクションでは、説明の正確な動作、 MoveNextCurrentDisposeのメンバー、IEnumerableIEnumerable<T>インターフェイスの列挙子オブジェクトによって提供される実装です。The following sections describe the exact behavior of the MoveNext, Current, and Dispose members of the IEnumerable and IEnumerable<T> interface implementations provided by an enumerator object.

列挙子オブジェクトはサポートされないことに注意してください、IEnumerator.Resetメソッド。Note that enumerator objects do not support the IEnumerator.Reset method. このメソッドを呼び出すと、System.NotSupportedExceptionがスローされます。Invoking this method causes a System.NotSupportedException to be thrown.

MoveNext メソッドThe MoveNext method

MoveNext列挙子オブジェクトのメソッドは、反復子ブロックのコードをカプセル化します。The MoveNext method of an enumerator object encapsulates the code of an iterator block. 呼び出す、MoveNextメソッド、反復子ブロックとセット内のコードの実行、Currentとして適切な列挙子オブジェクトのプロパティ。Invoking the MoveNext method executes code in the iterator block and sets the Current property of the enumerator object as appropriate. 実行した正確な動作MoveNext列挙子オブジェクトの状態によって異なるときMoveNextが呼び出されます。The precise action performed by MoveNext depends on the state of the enumerator object when MoveNext is invoked:

  • 列挙子オブジェクトの状態が場合する前に呼び出すと、 MoveNext:If the state of the enumerator object is before, invoking MoveNext:
    • 状態を変更してを実行しているします。Changes the state to running.
    • パラメーターを初期化します (などthis) 引数の値とインスタンス値の列挙子オブジェクトが初期化されたときに保存するには、反復子ブロックの。Initializes the parameters (including this) of the iterator block to the argument values and instance value saved when the enumerator object was initialized.
    • (後述) の実行が中断されるまでは、反復子ブロックを最初から実行します。Executes the iterator block from the beginning until execution is interrupted (as described below).
  • 列挙子オブジェクトの状態が場合を実行している、呼び出しの結果MoveNextが指定されていません。If the state of the enumerator object is running, the result of invoking MoveNext is unspecified.
  • 列挙子オブジェクトの状態が場合中断呼び出すと、 MoveNext:If the state of the enumerator object is suspended, invoking MoveNext:
    • 状態を変更してを実行しているします。Changes the state to running.
    • 最後に、反復子ブロックの実行が中断したときに保存する値には、すべてのローカル変数とパラメーター (これを含む) の値を復元します。Restores the values of all local variables and parameters (including this) to the values saved when execution of the iterator block was last suspended. これらの変数によって参照される任意のオブジェクトの内容は、MoveNext の以前の呼び出し以降に変更された可能性がありますに注意してください。Note that the contents of any objects referenced by these variables may have changed since the previous call to MoveNext.
    • 直後に、次の反復子ブロックの実行を再開、yield returnステートメントを実行の中断の原因となった、(後述) の実行が中断されるまで継続します。Resumes execution of the iterator block immediately following the yield return statement that caused the suspension of execution and continues until execution is interrupted (as described below).
  • 列挙子オブジェクトの状態が場合呼び出すと、MoveNext返しますfalseします。If the state of the enumerator object is after, invoking MoveNext returns false.

ときにMoveNext反復子ブロックを実行します。 4 つの方法で実行を中断できます。によって、yield returnステートメントにより、yield breakステートメントでは、例外と、反復子ブロックの最後の発生によってがスローされ、反復子ブロックの外部で伝達されます。When MoveNext executes the iterator block, execution can be interrupted in four ways: By a yield return statement, by a yield break statement, by encountering the end of the iterator block, and by an exception being thrown and propagated out of the iterator block.

  • ときに、yield returnステートメントが見つかりました (yield ステートメント)。When a yield return statement is encountered (The yield statement):
    • ステートメントで指定された式が評価、暗黙的に、yield 型に変換されに割り当てられている、Current列挙子オブジェクトのプロパティ。The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the Current property of the enumerator object.
    • 反復子本体の実行が中断されます。Execution of the iterator body is suspended. すべてのローカル変数とパラメーターの値 (などthis) のこの場所は、保存はyield returnステートメント。The values of all local variables and parameters (including this) are saved, as is the location of this yield return statement. 場合、yield return内で 1 つまたは複数のステートメントがtryブロック、関連付けられているfinallyブロックは、この時点では実行されません。If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
    • 列挙子オブジェクトの状態に変更中断します。The state of the enumerator object is changed to suspended.
    • MoveNextメソッドを返します。trueイテレーションは、次の値に正常に進んだことを示す、呼び出し元にします。The MoveNext method returns true to its caller, indicating that the iteration successfully advanced to the next value.
  • ときに、yield breakステートメントが見つかりました (yield ステートメント)。When a yield break statement is encountered (The yield statement):
    • 場合、yield break内で 1 つまたは複数のステートメントがtryブロック、関連付けられているfinallyブロックが実行されます。If the yield break statement is within one or more try blocks, the associated finally blocks are executed.
    • 列挙子オブジェクトの状態に変更します。The state of the enumerator object is changed to after.
    • MoveNextメソッドを返します。falseイテレーションが完了したことを示す、呼び出し元にします。The MoveNext method returns false to its caller, indicating that the iteration is complete.
  • ときに、反復子本体の末尾が発生しました。When the end of the iterator body is encountered:
    • 列挙子オブジェクトの状態に変更します。The state of the enumerator object is changed to after.
    • MoveNextメソッドを返します。falseイテレーションが完了したことを示す、呼び出し元にします。The MoveNext method returns false to its caller, indicating that the iteration is complete.
  • ときに例外がスローされ、反復子ブロックの外部で伝達します。When an exception is thrown and propagated out of the iterator block:
    • 適切なfinally反復子本体のブロックが例外の反映によって実行されるは。Appropriate finally blocks in the iterator body will have been executed by the exception propagation.
    • 列挙子オブジェクトの状態に変更します。The state of the enumerator object is changed to after.
    • 例外の反映の呼び出し元は引き続き、MoveNextメソッド。The exception propagation continues to the caller of the MoveNext method.

現在のプロパティThe Current property

列挙子オブジェクトのCurrentによってプロパティの影響を受けるyield return反復子ブロック内のステートメント。An enumerator object's Current property is affected by yield return statements in the iterator block.

列挙子オブジェクトの場合、中断状態では、値Current以前の呼び出しによって設定された値は、MoveNextします。When an enumerator object is in the suspended state, the value of Current is the value set by the previous call to MoveNext. 列挙子オブジェクトの場合、する前にを実行している、またはへのアクセスの結果が示すCurrentが指定されていません。When an enumerator object is in the before, running, or after states, the result of accessing Current is unspecified.

以外の入力を yield を使った反復子のためobjectへのアクセス結果Currentで列挙子オブジェクトのIEnumerableへのアクセスに対応する実装Currentで列挙子オブジェクトのIEnumerator<T>実装と、その結果をキャストobjectします。For an iterator with a yield type other than object, the result of accessing Current through the enumerator object's IEnumerable implementation corresponds to accessing Current through the enumerator object's IEnumerator<T> implementation and casting the result to object.

Dispose メソッドThe Dispose method

Disposeメソッドを使用列挙子オブジェクトを導入することで、イテレーションのクリーンアップを状態。The Dispose method is used to clean up the iteration by bringing the enumerator object to the after state.

  • 列挙子オブジェクトの状態が場合する前に呼び出すと、Dispose状態を変更してIf the state of the enumerator object is before, invoking Dispose changes the state to after.
  • 列挙子オブジェクトの状態が場合を実行している、呼び出しの結果Disposeが指定されていません。If the state of the enumerator object is running, the result of invoking Dispose is unspecified.
  • 列挙子オブジェクトの状態が場合中断呼び出すと、 Dispose:If the state of the enumerator object is suspended, invoking Dispose:
    • 状態を変更してを実行しているします。Changes the state to running.
    • いずれかの finally ブロックを実行、最後に実行された場合、yield returnステートメントが、yield breakステートメント。Executes any finally blocks as if the last executed yield return statement were a yield break statement. これによって、例外がスローされ、反復子本体の外部で伝達する場合、列挙子オブジェクトの状態に設定されての呼び出し元に例外が伝達されると、Disposeメソッド。If this causes an exception to be thrown and propagated out of the iterator body, the state of the enumerator object is set to after and the exception is propagated to the caller of the Dispose method.
    • 状態を変更してします。Changes the state to after.
  • 列挙子オブジェクトの状態が場合呼び出すと、Dispose効力はなくなりました。If the state of the enumerator object is after, invoking Dispose has no affect.

列挙可能なオブジェクトEnumerable objects

反復子ブロックを使用して、列挙可能なインターフェイスの型を返す関数のメンバーが実装されている関数メンバーを呼び出しても反復子ブロックのコードはすぐに実行されません。When a function member returning an enumerable interface type is implemented using an iterator block, invoking the function member does not immediately execute the code in the iterator block. 代わりに、列挙可能なオブジェクトが作成され、返されます。Instead, an enumerable object is created and returned. 列挙可能なオブジェクトのGetEnumeratorメソッドを返します、反復子ブロックで指定された列挙子オブジェクトをコードをカプセル化して、反復子ブロック内のコードの実行が発生したときに列挙子オブジェクトのMoveNextメソッドが呼び出されます。The enumerable object's GetEnumerator method returns an enumerator object that encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object's MoveNext method is invoked. 列挙可能なオブジェクトには、次の特徴があります。An enumerable object has the following characteristics:

  • 実装IEnumerableIEnumerable<T>ここで、T反復子の yield 型です。It implements IEnumerable and IEnumerable<T>, where T is the yield type of the iterator.
  • 引数の値のコピーの初期化 (ある場合) および関数メンバーに渡されるインスタンスの値。It is initialized with a copy of the argument values (if any) and instance value passed to the function member.

列挙可能なオブジェクトは、通常の反復子ブロック内のコードをカプセル化し、列挙可能なインターフェイスを実装するための列挙可能なクラスがコンパイラによって生成されたインスタンスが、他のメソッドの実装が可能です。An enumerable object is typically an instance of a compiler-generated enumerable class that encapsulates the code in the iterator block and implements the enumerable interfaces, but other methods of implementation are possible. 場合は、列挙可能なクラスは、コンパイラによって生成される、そのクラスが入れ子にする、直接または間接的には、関数メンバーを含むクラスで private のアクセシビリティがおよびコンパイラを使用するために予約された名前になります (識別子).If an enumerable class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function member, it will have private accessibility, and it will have a name reserved for compiler use (Identifiers).

列挙可能なオブジェクトは、上記で指定したものよりもいないインターフェイスを実装することができます。An enumerable object may implement more interfaces than those specified above. 具体的には、列挙可能なオブジェクトも実装IEnumeratorIEnumerator<T>、列挙型と列挙子の両方として機能するようにします。In particular, an enumerable object may also implement IEnumerator and IEnumerator<T>, enabling it to serve as both an enumerable and an enumerator. このような実装では、最初の時間、列挙可能なオブジェクトのGetEnumeratorメソッドが呼び出される列挙可能なオブジェクトが返されます。In that type of implementation, the first time an enumerable object's GetEnumerator method is invoked, the enumerable object itself is returned. 列挙可能なオブジェクトの後に呼び出さGetEnumerator列挙可能なオブジェクトのコピーを返す場合は、します。Subsequent invocations of the enumerable object's GetEnumerator, if any, return a copy of the enumerable object. したがって、各エラーは、列挙子が独自の状態と、1 つの列挙子で変更が別に影響することはありません返されます。Thus, each returned enumerator has its own state and changes in one enumerator will not affect another.

GetEnumerator メソッドThe GetEnumerator method

列挙可能なオブジェクトの実装を提供する、GetEnumeratorのメソッド、IEnumerableIEnumerable<T>インターフェイス。An enumerable object provides an implementation of the GetEnumerator methods of the IEnumerable and IEnumerable<T> interfaces. 2 つGetEnumeratorメソッドを取得し、使用可能な列挙子オブジェクトを取得する一般的な実装を共有します。The two GetEnumerator methods share a common implementation that acquires and returns an available enumerator object. 列挙子オブジェクトが引数の値で初期化され、インスタンスの列挙可能なオブジェクトが初期化されますが、それ以外の場合に保存された値で説明されているように機能列挙子オブジェクトします。The enumerator object is initialized with the argument values and instance value saved when the enumerable object was initialized, but otherwise the enumerator object functions as described in Enumerator objects.

実装例Implementation example

このセクションでは、標準 c# コンストラクトの観点からの反復子の実装について説明します。This section describes a possible implementation of iterators in terms of standard C# constructs. ここで説明されている実装 Microsoft c# コンパイラで使用される同じ原則に基づいていますが、規制に準拠した実装または使用可能な 1 つだけではではありません。The implementation described here is based on the same principles used by the Microsoft C# compiler, but it is by no means a mandated implementation or the only one possible.

Stack<T>クラスが実装するそのGetEnumeratorメソッド、反復子を使用します。The following Stack<T> class implements its GetEnumerator method using an iterator. 反復子は、上から下へのスタックの要素を列挙します。The iterator enumerates the elements of the stack in top to bottom order.

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

class Stack<T>: IEnumerable<T>
{
    T[] items;
    int count;

    public void Push(T item) {
        if (items == null) {
            items = new T[4];
        }
        else if (items.Length == count) {
            T[] newItems = new T[count * 2];
            Array.Copy(items, 0, newItems, 0, count);
            items = newItems;
        }
        items[count++] = item;
    }

    public T Pop() {
        T result = items[--count];
        items[count] = default(T);
        return result;
    }

    public IEnumerator<T> GetEnumerator() {
        for (int i = count - 1; i >= 0; --i) yield return items[i];
    }
}

GetEnumeratorメソッドは、次に示すように、反復子ブロックでコードをカプセル化する列挙子のコンパイラによって生成されたクラスのインスタンス化に変換できます。The GetEnumerator method can be translated into an instantiation of a compiler-generated enumerator class that encapsulates the code in the iterator block, as shown in the following.

class Stack<T>: IEnumerable<T>
{
    ...

    public IEnumerator<T> GetEnumerator() {
        return new __Enumerator1(this);
    }

    class __Enumerator1: IEnumerator<T>, IEnumerator
    {
        int __state;
        T __current;
        Stack<T> __this;
        int i;

        public __Enumerator1(Stack<T> __this) {
            this.__this = __this;
        }

        public T Current {
            get { return __current; }
        }

        object IEnumerator.Current {
            get { return __current; }
        }

        public bool MoveNext() {
            switch (__state) {
                case 1: goto __state1;
                case 2: goto __state2;
            }
            i = __this.count - 1;
        __loop:
            if (i < 0) goto __state2;
            __current = __this.items[i];
            __state = 1;
            return true;
        __state1:
            --i;
            goto __loop;
        __state2:
            __state = 2;
            return false;
        }

        public void Dispose() {
            __state = 2;
        }

        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }
    }
}

反復子ブロック内のコードをステート マシンに変換されに配置前の変換で、MoveNext列挙子クラスのメソッド。In the preceding translation, the code in the iterator block is turned into a state machine and placed in the MoveNext method of the enumerator class. さらに、ローカル変数iの呼び出し間での存在を続行できるように、列挙子オブジェクトのフィールドになってMoveNextします。Furthermore, the local variable i is turned into a field in the enumerator object so it can continue to exist across invocations of MoveNext.

次の例では、整数 1 ~ 10 の単純な掛け算表を印刷します。The following example prints a simple multiplication table of the integers 1 through 10. FromToメソッドの例では列挙可能なオブジェクトを返し、反復子を使用して実装されます。The FromTo method in the example returns an enumerable object and is implemented using an iterator.

using System;
using System.Collections.Generic;

class Test
{
    static IEnumerable<int> FromTo(int from, int to) {
        while (from <= to) yield return from++;
    }

    static void Main() {
        IEnumerable<int> e = FromTo(1, 10);
        foreach (int x in e) {
            foreach (int y in e) {
                Console.Write("{0,3} ", x * y);
            }
            Console.WriteLine();
        }
    }
}

FromToメソッドは、次に示すように、反復子ブロック内のコードをカプセル化するための列挙可能なクラスがコンパイラによって生成されたインスタンス化に変換できます。The FromTo method can be translated into an instantiation of a compiler-generated enumerable class that encapsulates the code in the iterator block, as shown in the following.

using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;

class Test
{
    ...

    static IEnumerable<int> FromTo(int from, int to) {
        return new __Enumerable1(from, to);
    }

    class __Enumerable1:
        IEnumerable<int>, IEnumerable,
        IEnumerator<int>, IEnumerator
    {
        int __state;
        int __current;
        int __from;
        int from;
        int to;
        int i;

        public __Enumerable1(int __from, int to) {
            this.__from = __from;
            this.to = to;
        }

        public IEnumerator<int> GetEnumerator() {
            __Enumerable1 result = this;
            if (Interlocked.CompareExchange(ref __state, 1, 0) != 0) {
                result = new __Enumerable1(__from, to);
                result.__state = 1;
            }
            result.from = result.__from;
            return result;
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return (IEnumerator)GetEnumerator();
        }

        public int Current {
            get { return __current; }
        }

        object IEnumerator.Current {
            get { return __current; }
        }

        public bool MoveNext() {
            switch (__state) {
            case 1:
                if (from > to) goto case 2;
                __current = from++;
                __state = 1;
                return true;
            case 2:
                __state = 2;
                return false;
            default:
                throw new InvalidOperationException();
            }
        }

        public void Dispose() {
            __state = 2;
        }

        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }
    }
}

列挙可能なクラスでは、列挙可能なインターフェイスと列挙型および列挙子の両方として機能できるように、列挙子インターフェイスの両方を実装します。The enumerable class implements both the enumerable interfaces and the enumerator interfaces, enabling it to serve as both an enumerable and an enumerator. 最初に、GetEnumeratorメソッドが呼び出される列挙可能なオブジェクトが返されます。The first time the GetEnumerator method is invoked, the enumerable object itself is returned. 列挙可能なオブジェクトの後に呼び出さGetEnumerator列挙可能なオブジェクトのコピーを返す場合は、します。Subsequent invocations of the enumerable object's GetEnumerator, if any, return a copy of the enumerable object. したがって、各エラーは、列挙子が独自の状態と、1 つの列挙子で変更が別に影響することはありません返されます。Thus, each returned enumerator has its own state and changes in one enumerator will not affect another. Interlocked.CompareExchangeメソッドを使用して、スレッド セーフ操作を確認します。The Interlocked.CompareExchange method is used to ensure thread-safe operation.

fromtoパラメーターは列挙可能なクラスのフィールドに変換されます。The from and to parameters are turned into fields in the enumerable class. from反復子ブロックでは、追加で変更が__fromに指定された初期値を保持するフィールドが導入されましたfrom各列挙子にします。Because from is modified in the iterator block, an additional __from field is introduced to hold the initial value given to from in each enumerator.

MoveNextメソッドがスローされます、InvalidOperationExceptionときに呼び出された場合__state0します。The MoveNext method throws an InvalidOperationException if it is called when __state is 0. これで最初に呼び出さず、列挙子オブジェクトとしての列挙可能なオブジェクトの使用に対して保護GetEnumeratorします。This protects against use of the enumerable object as an enumerator object without first calling GetEnumerator.

次の例では、単純なツリーのクラスを示します。The following example shows a simple tree class. Tree<T>クラスが実装するそのGetEnumeratorメソッド、反復子を使用します。The Tree<T> class implements its GetEnumerator method using an iterator. 反復子は、infix ツリーの要素を列挙します。The iterator enumerates the elements of the tree in infix order.

using System;
using System.Collections.Generic;

class Tree<T>: IEnumerable<T>
{
    T value;
    Tree<T> left;
    Tree<T> right;

    public Tree(T value, Tree<T> left, Tree<T> right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public IEnumerator<T> GetEnumerator() {
        if (left != null) foreach (T x in left) yield x;
        yield value;
        if (right != null) foreach (T x in right) yield x;
    }
}

class Program
{
    static Tree<T> MakeTree<T>(T[] items, int left, int right) {
        if (left > right) return null;
        int i = (left + right) / 2;
        return new Tree<T>(items[i], 
            MakeTree(items, left, i - 1),
            MakeTree(items, i + 1, right));
    }

    static Tree<T> MakeTree<T>(params T[] items) {
        return MakeTree(items, 0, items.Length - 1);
    }

    // The output of the program is:
    // 1 2 3 4 5 6 7 8 9
    // Mon Tue Wed Thu Fri Sat Sun

    static void Main() {
        Tree<int> ints = MakeTree(1, 2, 3, 4, 5, 6, 7, 8, 9);
        foreach (int i in ints) Console.Write("{0} ", i);
        Console.WriteLine();

        Tree<string> strings = MakeTree(
            "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
        foreach (string s in strings) Console.Write("{0} ", s);
        Console.WriteLine();
    }
}

GetEnumeratorメソッドは、次に示すように、反復子ブロックでコードをカプセル化する列挙子のコンパイラによって生成されたクラスのインスタンス化に変換できます。The GetEnumerator method can be translated into an instantiation of a compiler-generated enumerator class that encapsulates the code in the iterator block, as shown in the following.

class Tree<T>: IEnumerable<T>
{
    ...

    public IEnumerator<T> GetEnumerator() {
        return new __Enumerator1(this);
    }

    class __Enumerator1 : IEnumerator<T>, IEnumerator
    {
        Node<T> __this;
        IEnumerator<T> __left, __right;
        int __state;
        T __current;

        public __Enumerator1(Node<T> __this) {
            this.__this = __this;
        }

        public T Current {
            get { return __current; }
        }

        object IEnumerator.Current {
            get { return __current; }
        }

        public bool MoveNext() {
            try {
                switch (__state) {

                case 0:
                    __state = -1;
                    if (__this.left == null) goto __yield_value;
                    __left = __this.left.GetEnumerator();
                    goto case 1;

                case 1:
                    __state = -2;
                    if (!__left.MoveNext()) goto __left_dispose;
                    __current = __left.Current;
                    __state = 1;
                    return true;

                __left_dispose:
                    __state = -1;
                    __left.Dispose();

                __yield_value:
                    __current = __this.value;
                    __state = 2;
                    return true;

                case 2:
                    __state = -1;
                    if (__this.right == null) goto __end;
                    __right = __this.right.GetEnumerator();
                    goto case 3;

                case 3:
                    __state = -3;
                    if (!__right.MoveNext()) goto __right_dispose;
                    __current = __right.Current;
                    __state = 3;
                    return true;

                __right_dispose:
                    __state = -1;
                    __right.Dispose();

                __end:
                    __state = 4;
                    break;

                }
            }
            finally {
                if (__state < 0) Dispose();
            }
            return false;
        }

        public void Dispose() {
            try {
                switch (__state) {

                case 1:
                case -2:
                    __left.Dispose();
                    break;

                case 3:
                case -3:
                    __right.Dispose();
                    break;

                }
            }
            finally {
                __state = 4;
            }
        }

        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }
    }
}

使用されるコンパイラによって生成された一時、foreachにステートメントが無効になる、__left__right列挙子オブジェクトのフィールド。The compiler generated temporaries used in the foreach statements are lifted into the __left and __right fields of the enumerator object. __state列挙子オブジェクトのフィールドは、慎重に更新できるように、正しいDispose()メソッドが正しく呼び出される場合は、例外がスローされます。The __state field of the enumerator object is carefully updated so that the correct Dispose() method will be called correctly if an exception is thrown. 翻訳された単純なコードを記述することはできませんに注意してください。foreachステートメント。Note that it is not possible to write the translated code with simple foreach statements.

非同期関数Async functions

メソッド (メソッド) または匿名関数 (匿名関数式) で、async修飾子と呼ばれる、非同期関数します。A method (Methods) or anonymous function (Anonymous function expressions) with the async modifier is called an async function. 一般に、用語async任意の種類を持つ関数の記述に使用される、async修飾子。In general, the term async is used to describe any kind of function that has the async modifier.

いずれかを指定する非同期関数の仮パラメーター リストと、コンパイル時エラーrefまたはoutパラメーター。It is a compile-time error for the formal parameter list of an async function to specify any ref or out parameters.

Return_type 、非同期のメソッドはいずれかのことがありますvoidまたはタスクの種類します。The return_type of an async method must be either void or a task type. タスクの種類はSystem.Threading.Tasks.Taskから型を構築およびSystem.Threading.Tasks.Task<T>します。The task types are System.Threading.Tasks.Task and types constructed from System.Threading.Tasks.Task<T>. 説明を簡潔にするため、この章ではこれらの型として参照されますTaskTask<T>、それぞれします。For the sake of brevity, in this chapter these types are referenced as Task and Task<T>, respectively. タスク型を返す非同期メソッドは、タスクを返すと言います。An async method returning a task type is said to be task-returning.

タスクの種類の正確な定義が定義されている、実装が、言語の観点から、タスクの型がのいずれか、不完全な状態が成功したか、エラーが発生しました。The exact definition of the task types is implementation defined, but from the language's point of view a task type is in one of the states incomplete, succeeded or faulted. エラーが発生したタスクは、関連する例外を記録します。A faulted task records a pertinent exception. 成功、Task<T>型の結果を記録Tします。A succeeded Task<T> records a result of type T. タスクの種類は待機可能なとのオペランドは、そのため、await 式 (Await 式)。Task types are awaitable, and can therefore be the operands of await expressions (Await expressions).

非同期関数の呼び出しが評価を停止することでは、await 式 (Await 式) 本体内にします。An async function invocation has the ability to suspend evaluation by means of await expressions (Await expressions) in its body. 評価を中断時点では後で再開が await 式で、再開デリゲートします。Evaluation may later be resumed at the point of the suspending await expression by means of a resumption delegate. 再開のデリゲートは型System.Action、非同期関数の呼び出しの評価が箇所の await 式から再開されるメソッドが呼び出されたときにします。The resumption delegate is of type System.Action, and when it is invoked, evaluation of the async function invocation will resume from the await expression where it left off. 現在の呼び出し元非同期関数の呼び出しは最初の呼び出し元関数の呼び出しは中断されていることはない場合、または再開デリゲートの最新の呼び出し元それ以外の場合。The current caller of an async function invocation is the original caller if the function invocation has never been suspended, or the most recent caller of the resumption delegate otherwise.

非同期タスクを返す関数の評価Evaluation of a task-returning async function

タスクを返す非同期関数の呼び出しにより、生成するタスクが返される型のインスタンス。Invocation of a task-returning async function causes an instance of the returned task type to be generated. これと呼ばれますが、タスクを返すの async 関数。This is called the return task of the async function. タスクは、不完全な状態の初期段階です。The task is initially in an incomplete state.

非同期関数の本体は評価されます (await 式に到達) によって中断されていたか、またはが終了するまでタスクを返すと、呼び出し元にコントロールのポイントが返されます。The async function body is then evaluated until it is either suspended (by reaching an await expression) or terminates, at which point control is returned to the caller, along with the return task.

非同期関数の本体が終了すると、タスクを返すに不完全な状態から移動されます。When the body of the async function terminates, the return task is moved out of the incomplete state:

  • Return ステートメントまたは本体の末尾に到達の結果として、関数本体が終了すると、成功の状態に、戻り値のタスクで、結果の値が記録されます。If the function body terminates as the result of reaching a return statement or the end of the body, any result value is recorded in the return task, which is put into a succeeded state.
  • キャッチされない例外の結果として、関数本体が終了しているかどうか (throw ステートメント) エラーが発生した状態に戻り、タスクに例外が記録されます。If the function body terminates as the result of an uncaught exception (The throw statement) the exception is recorded in the return task which is put into a faulted state.

Async void を返す関数の評価Evaluation of a void-returning async function

非同期関数の戻り値の型がある場合void、次のように、上記とは異なる評価。関数が完了と、現在のスレッドの例外に伝える代わりにタスクが返されないため同期コンテキストします。If the return type of the async function is void, evaluation differs from the above in the following way: Because no task is returned, the function instead communicates completion and exceptions to the current thread's synchronization context. 同期コンテキストの正確な定義は実装に依存しますが、表現である"where"現在のスレッドが実行されているのです。The exact definition of synchronization context is implementation-dependent, but is a representation of "where" the current thread is running. 同期コンテキストは、async void を返す関数の評価の開始が正常に完了すると、またはキャッチされない例外がスローされると、ときに通知されます。The synchronization context is notified when evaluation of a void-returning async function commences, completes successfully, or causes an uncaught exception to be thrown.

これにより、コンテキスト、その下にある数の void を返す非同期関数が実行されているを追跡して、それらから例外を伝達する方法を決定できます。This allows the context to keep track of how many void-returning async functions are running under it, and to decide how to propagate exceptions coming out of them.