言語への非依存性、および言語非依存コンポーネントLanguage Independence and Language-Independent Components

.NET Framework は言語に依存しません。The .NET Framework is language independent. つまり、C++/CLI、Eiffel、F#、IronPython、IronRuby、PowerBuilder、Visual Basic、Visual COBOL、Windows PowerShell など、.NET Framework を対象とする多くの言語の 1 つを開発に使用できます。This means that, as a developer, you can develop in one of the many languages that target the .NET Framework, such as C#, C++/CLI, Eiffel, F#, IronPython, IronRuby, PowerBuilder, Visual Basic, Visual COBOL, and Windows PowerShell. .NET Framework 用に開発されたクラス ライブラリの型とメンバーには、最初に記述された言語を知らなくてもアクセスできます。元の言語の規則に従う必要もありません。You can access the types and members of class libraries developed for the .NET Framework without having to know the language in which they were originally written and without having to follow any of the original language's conventions. コンポーネントを開発しているのであれば、コンポーネントの言語にかかわらず、すべての .NET Framework アプリからそのコンポーネントにアクセスできます。If you are a component developer, your component can be accessed by any .NET Framework app regardless of its language.

注意

この記事の最初の部分では、言語に依存しないコンポーネント、つまり、どの言語で記述されたアプリからでも使用できるコンポーネントの作成について説明します。This first part of this article discusses creating language-independent components—that is, components that can be consumed by apps that are written in any language. また、複数の言語で記述されたソース コードから 1 つのコンポーネントまたはアプリを作成することもできます。この記事の 2 番目のパートにある「言語間の相互運用性」を参照してください。You can also create a single component or app from source code written in multiple languages; see Cross-Language Interoperability in the second part of this article.

任意の言語で記述された他のオブジェクトと完全に対話するには、すべての言語に共通の機能だけを呼び出し側に公開するようにオブジェクトを実装する必要があります。To fully interact with other objects written in any language, objects must expose to callers only those features that are common to all languages. この共通の機能セットは、生成されたアセンブリに適用される規則のセットである、共通言語仕様 (CLS: Common Language Specification) によって定義されます。This common set of features is defined by the Common Language Specification (CLS), which is a set of rules that apply to generated assemblies. 共通言語仕様は、「ECMA-335 Standard: Common Language Infrastructure」(標準の ECMA-335: 共通言語基盤) の第 1 部の第 7 ~ 11 項で定義されています。The Common Language Specification is defined in Partition I, Clauses 7 through 11 of the ECMA-335 Standard: Common Language Infrastructure.

コンポーネントが共通言語仕様に準拠している場合は、CLS に準拠することが保証され、CLS をサポートするすべてのプログラミング言語で記述されたアセンブリのコードからアクセスできます。If your component conforms to the Common Language Specification, it is guaranteed to be CLS-compliant and can be accessed from code in assemblies written in any programming language that supports the CLS. コンパイル時にコンポーネントが共通言語仕様に準拠しているかどうかを確認するには、CLSCompliantAttribute 属性をソース コードに適用します。You can determine whether your component conforms to the Common Language Specification at compile time by applying the CLSCompliantAttribute attribute to your source code. 詳細については、「CLSCompliantAttribute 属性」を参照してください。For more information, see The CLSCompliantAttribute attribute.

この記事の内容:In this article:

CLS 準拠の規則CLS compliance rules

ここでは、CLS に準拠したコンポーネントを作成するための規則について説明します。This section discusses the rules for creating a CLS-compliant component. 規則規則の完全な一覧については、「ECMA-335 Standard: Common Language Infrastructure」(標準の ECMA-335: 共通言語基盤) の第 1 部の第 11 項を参照してください。For a complete list of rules, see Partition I, Clause 11 of the ECMA-335 Standard: Common Language Infrastructure.

注意

共通言語仕様では、コンシューマー (プログラムによって CLS 準拠のコンポーネントにアクセスする開発者)、フレームワーク (言語コンパイラを使用して CLS 準拠のライブラリを作成する開発者)、およびエクステンダー (CLS 準拠のコンポーネントを作成する言語コンパイラ、コード パーサーなどのツールを作成する開発者) に適用する、CLS 準拠の各規則について説明します。The Common Language Specification discusses each rule for CLS compliance as it applies to consumers (developers who are programmatically accessing a component that is CLS-compliant), frameworks (developers who are using a language compiler to create CLS-compliant libraries), and extenders (developers who are creating a tool such as a language compiler or a code parser that creates CLS-compliant components). ここでは、フレームワークに適用するときの規則に焦点を当てます。This article focuses on the rules as they apply to frameworks. エクステンダーに適用する一部の規則は、Reflection.Emit を使用して作成されたアセンブリに適用されることもあります。Note, though, that some of the rules that apply to extenders may also apply to assemblies that are created using Reflection.Emit.

言語に依存しないコンポーネントをデザインするには、コンポーネントのパブリック インターフェイスに CLS 準拠の規則を適用するだけです。To design a component that is language independent, you only need to apply the rules for CLS compliance to your component's public interface. プライベートな実装は仕様に準拠する必要はありません。Your private implementation does not have to conform to the specification.

重要

CLS 準拠の規則は、コンポーネントのパブリック インターフェイスにのみ適用されます。プライベート実装には適用されません。The rules for CLS compliance apply only to a component's public interface, not to its private implementation.

たとえば、Byte 以外の符号なし整数は CLS に準拠していません。For example, unsigned integers other than Byte are not CLS-compliant. 次の例の Person クラスは型 AgeUInt16 プロパティを公開するので、次のコードではコンパイラの警告が表示されます。Because the Person class in the following example exposes an Age property of type UInt16, the following code displays a compiler warning.

using System;

[assembly: CLSCompliant(true)]

public class Person
{
   private UInt16 personAge = 0;

   public UInt16 Age 
   { get { return personAge; } }
}
// The attempt to compile the example displays the following compiler warning:
//    Public1.cs(10,18): warning CS3003: Type of 'Person.Age' is not CLS-compliant
<Assembly: CLSCompliant(True)> 

Public Class Person
   Private personAge As UInt16
   
   Public ReadOnly Property Age As UInt16
      Get
         Return personAge      
      End Get   
   End Property
End Class
' The attempt to compile the example displays the following compiler warning:
'    Public1.vb(9) : warning BC40027: Return type of function 'Age' is not CLS-compliant.
'    
'       Public ReadOnly Property Age As UInt16
'                                ~~~

Person クラスを CLS 準拠にするには、Age プロパティの型を UInt16 から、CLS 準拠の 16 ビット符号付き整数である Int16 に変更します。You can make the Person class CLS-compliant by changing the type of Age property from UInt16 to Int16, which is a CLS-compliant, 16-bit signed integer. プライベート personAge フィールドの型を変更する必要はありません。You do not have to change the type of the private personAge field.

using System;

[assembly: CLSCompliant(true)]

public class Person
{
   private Int16 personAge = 0;

   public Int16 Age 
   { get { return personAge; } }
}
<Assembly: CLSCompliant(True)> 

Public Class Person
   Private personAge As UInt16
   
   Public ReadOnly Property Age As Int16
      Get
         Return CType(personAge, Int16)      
      End Get   
   End Property
End Class

ライブラリのパブリック インターフェイスは、次の要素で構成されます。A library's public interface consists of the following:

  • パブリック クラスの定義。Definitions of public classes.

  • パブリック クラスのパブリック メンバーの定義、および派生クラスからアクセスできるメンバー (つまり、protected メンバー) の定義。Definitions of the public members of public classes, and definitions of members accessible to derived classes (that is, protected members).

  • パブリック クラスのパブリック メソッドのパラメーターおよび戻り値の型、派生クラスからアクセスできるメソッドのパラメーターおよび戻り値の型。Parameters and return types of public methods of public classes, and parameters and return types of methods accessible to derived classes.

CLS 準拠の規則を次の表に示します。The rules for CLS compliance are listed in the following table. これらの規則のテキストは、「ECMA-335 Standard: Common Language Infrastructure」(標準の ECMA-335: 共通言語基盤) からの引用で、Ecma International が 2012 年の著作権を保有しています。The text of the rules is taken verbatim from the ECMA-335 Standard: Common Language Infrastructure, which is Copyright 2012 by Ecma International. これらの規則の詳細については、以降のセクションを参照してください。More detailed information about these rules is found in the following sections.

カテゴリCategory 解決方法については、See ルールRule 規則番号Rule number
ユーザー補助Accessibility メンバーのアクセシビリティMember accessibility 継承されたメソッドをオーバーライドする場合、アクセシビリティは変更してはいけない。ただし、別のアセンブリから継承されたメソッドをアクセシビリティ family-or-assembly でオーバーライドする場合は除く。Accessibility shall not be changed when overriding inherited methods, except when overriding a method inherited from a different assembly with accessibility family-or-assembly. この場合、オーバーライドのアクセシビリティは family にすること。In this case, the override shall have accessibility family. 1010
ユーザー補助Accessibility メンバーのアクセシビリティMember accessibility 型およびメンバーの可視性およびアクセシビリティについて、メンバーのシグネチャに指定されている型は、そのメンバーが可視でアクセス可能な場合、必ず可視でアクセス可能でなければいけない。The visibility and accessibility of types and members shall be such that types in the signature of any member shall be visible and accessible whenever the member itself is visible and accessible. たとえば、アセンブリ外部から参照できるパブリックなメソッドには、アセンブリ内部でだけ可視である型が引数として含まれていてはいけない。For example, a public method that is visible outside its assembly shall not have an argument whose type is visible only within the assembly. メンバーのシグネチャに使用されているジェネリック型のインスタンスを構成する型の可視性およびアクセシビリティは、メンバーが可視でアクセス可能の場合、必ず可視でアクセス可能でなければいけない。The visibility and accessibility of types composing an instantiated generic type used in the signature of any member shall be visible and accessible whenever the member itself is visible and accessible. たとえば、アセンブリ外部から参照できるメンバーのシグネチャに指定されているジェネリック型のインスタンスに、アセンブリ内部でだけ可視である型の汎用引数が含まれていてはいけない。For example, an instantiated generic type present in the signature of a member that is visible outside its assembly shall not have a generic argument whose type is visible only within the assembly. 1212
配列Arrays 配列Arrays 配列は、要素が CLS 準拠型で、すべての次元でインデックス番号が 0 から始まらなければならない。Arrays shall have elements with a CLS-compliant type, and all dimensions of the array shall have lower bounds of zero. 項目が配列の場合、オーバーロードどうしを区別するには配列要素の型を必要とする。Only the fact that an item is an array and the element type of the array shall be required to distinguish between overloads. オーバーロードが 2 つ以上の配列型に基づく場合、要素型は名前付きの型でなければいけない。When overloading is based on two or more array types the element types shall be named types. 1616
属性Attributes 属性Attributes 属性の型 System.Attribute、またはそれを継承する型である。Attributes shall be of type System.Attribute, or a type inheriting from it. 4141
属性Attributes 属性Attributes CLS ではカスタム属性のエンコーディングのサブセットのみ使用できる。The CLS only allows a subset of the encodings of custom attributes. これらのエンコーディングに表示される型 (第 4 部を参照) は、System.TypeSystem.StringSystem.CharSystem.BooleanSystem.ByteSystem.Int16System.Int32System.Int64System.SingleSystem.Double、CLS 準拠の基底の整数型に基づく列挙型のみである。The only types that shall appear in these encodings are (see Partition IV): System.Type, System.String, System.Char, System.Boolean, System.Byte, System.Int16, System.Int32, System.Int64, System.Single, System.Double, and any enumeration type based on a CLS-compliant base integer type. 3434
属性Attributes 属性Attributes CLS では、公開参照される必須の修飾子 (modreq、第 2 部を参照) は使用できない。ただし、認識しないオプションの修飾子 (modopt、第 2 部を参照) は使用できる。The CLS does not allow publicly visible required modifiers (modreq, see Partition II), but does allow optional modifiers (modopt, see Partition II) it does not understand. 3535
コンストラクターConstructors コンストラクターConstructors オブジェクト コンストラクターでは、継承しているインスタンス データへのアクセスが発生する前に、基底クラスのインスタンス コンストラクターを呼び出さなければいけないAn object constructor shall call some instance constructor of its base class before any access occurs to inherited instance data. (コンストラクターが不要である値型は除く)。(This does not apply to value types, which need not have constructors.) 2121
コンストラクターConstructors コンストラクターConstructors オブジェクト コンストラクターがオブジェクトの作成時以外で呼び出されてはならず、またオブジェクトが 2 度初期化されてもいけない。An object constructor shall not be called except as part of the creation of an object, and an object shall not be initialized twice. 2222
列挙Enumerations 列挙型Enumerations enum の基になる型は組み込みの CLS 整数型、フィールド名は "value__" であり、そのフィールドには RTSpecialName のマークが付けられる。The underlying type of an enum shall be a built-in CLS integer type, the name of the field shall be "value__", and that field shall be marked RTSpecialName. 77
列挙型Enumerations 列挙型Enumerations enum には 2 種類あり、System.FlagsAttribute カスタム属性 (第 4 部のライブラリを参照) の有無で区別する。There are two distinct kinds of enums, indicated by the presence or absence of the System.FlagsAttribute (see Partition IV Library) custom attribute. 片方は名前付き整数値を表し、もう片方は名前付きビット フラグを表す。名前付きビット フラグは、それを組み合わせて名前のない値を生成できる。One represents named integer values; the other represents named bit flags that can be combined to generate an unnamed value. enum の値は、指定した値に限定されない。The value of an enum is not limited to the specified values. 88
列挙Enumerations 列挙型Enumerations enum のリテラルな静的フィールドの型は、その enum 自体の型である。Literal static fields of an enum shall have the type of the enum itself. 99
イベントEvents イベントEvents イベントを実装するメソッドは、メタデータ内で SpecialName のマークが付けられる。The methods that implement an event shall be marked SpecialName in the metadata. 2929
イベントEvents イベントEvents イベントとイベントのアクセサーのアクセシビリティは同一である。The accessibility of an event and of its accessors shall be identical. 3030
イベントEvents イベントEvents イベントの add メソッドおよび remove メソッドは、どちらもあってもなくてもよい。The add and remove methods for an event shall both either be present or absent. 3131
イベントEvents イベントEvents add メソッドおよび remove メソッドは、それぞれパラメーターを 1 つ使用する。このパラメーターの型がイベントの型を規定する。また、パラメーターの型は System.Delegate の派生でなければいけない。The add and remove methods for an event shall each take one parameter whose type defines the type of the event and that shall be derived from System.Delegate. 3232
イベントEvents イベントEvents イベントは、特定の名前付けパターンに従わなくてはいけない。Events shall adhere to a specific naming pattern. CLS 規則 29 で触れられている SpecialName 属性は、適切な名前比較で無視され、識別子規則に従わなければいけない。The SpecialName attribute referred to in CLS rule 29 shall be ignored in appropriate name comparisons and shall adhere to identifier rules. 3333
例外Exceptions 例外Exceptions スローできるオブジェクト型は、System.Exception、またはそれを継承する型である。Objects that are thrown shall be of type System.Exception or a type inheriting from it. ただし、CLS 準拠のメソッドで他の型の例外のスローをブロックする必要はない。Nonetheless, CLS-compliant methods are not required to block the propagation of other types of exceptions. 4040
全般General CLS 準拠: 規則CLS compliance: the Rules CLS 規則は、型の構成部分のうち、その型を定義しているアセンブリの外部からアクセスまたは参照できる部分にのみ適用される。CLS rules apply only to those parts of a type that are accessible or visible outside of the defining assembly. 11
全般General CLS 準拠: 規則CLS compliance: the Rules CLS 非準拠型のメンバーを CLS 準拠と指定しない。Members of non-CLS compliant types shall not be marked CLS-compliant. 22
ジェネリックGenerics ジェネリック型とメンバーGeneric types and members 入れ子になった型は、少なくともその外側の型と同じ数のジェネリック パラメーターを持つ。Nested types shall have at least as many generic parameters as the enclosing type. 入れ子にされた型のジェネリック パラメーターは、それを囲む型のジェネリック パラメーターと、位置によって対応します。Generic parameters in a nested type correspond by position to the generic parameters in its enclosing type. 4242
ジェネリックGenerics ジェネリック型とメンバーGeneric types and members ジェネリック型の名前は、入れ子にされない型で宣言される型パラメーターの数をエンコードする必要がある。入れ子にされる場合は、上記の規則に従って、型に新しく組み込まれる型パラメーターの数をエンコードする必要がある。The name of a generic type shall encode the number of type parameters declared on the non-nested type, or newly introduced to the type if nested, according to the rules defined above. 4343
ジェネリックGenerics ジェネリック型とメンバーGeneric types and members ジェネリック型は必要な制約を再宣言して、基本型またはインターフェイスの制約がジェネリック型の制約で確実に満たされるようにする必要がある。A generic type shall redeclare sufficient constraints to guarantee that any constraints on the base type, or interfaces would be satisfied by the generic type constraints. 44444444
ジェネリックGenerics ジェネリック型とメンバーGeneric types and members ジェネリック パラメーターの制約として使用される型は CLS に準拠する必要がある。Types used as constraints on generic parameters shall themselves be CLS-compliant. 4545
ジェネリックGenerics ジェネリック型とメンバーGeneric types and members インスタンス化されたジェネリック型のメンバー (入れ子になった型も含む) の可視性およびアクセシビリティは、ジェネリック型の全体の宣言ではなく、特定のインスタンス化に対してスコープが設定される必要がある。The visibility and accessibility of members (including nested types) in an instantiated generic type shall be considered to be scoped to the specific instantiation rather than the generic type declaration as a whole. この場合でも、CLS 規則 12 の可視性規則とアクセシビリティ規則は同様に適用される。Assuming this, the visibility and accessibility rules of CLS rule 12 still apply. 4646
ジェネリックGenerics ジェネリック型とメンバーGeneric types and members 抽象メソッドまたは仮想ジェネリック メソッドごとに、既定の具体的な実装がある。For each abstract or virtual generic method, there shall be a default concrete (non-abstract) implementation. 4747
インターフェイスInterfaces インターフェイスInterfaces CLS 準拠のインターフェイスでは、CLS に準拠しないメソッドを実装するために、これらを定義する必要はない。CLS-compliant interfaces shall not require the definition of non-CLS compliant methods in order to implement them. 1818
インターフェイスInterfaces インターフェイスInterfaces CLS 準拠インターフェイスでは、静的メソッドを定義してはいけない。また、フィールドも定義してはいけない。CLS-compliant interfaces shall not define static methods, nor shall they define fields. 1919
メンバーMembers 一般的な型メンバーType members in general グローバルで静的な (static) フィールドとメソッドは CLS 準拠ではありません。Global static fields and methods are not CLS-compliant. 3636
メンバーMembers -- 静的リテラル値の指定には、フィールド初期化メタデータを使用する。The value of a literal static is specified through the use of field initialization metadata. CLS 準拠のリテラルには、そのリテラルと同じ型 (または、そのリテラルが enum の場合は基本型) の値がフィールド初期化メタデータに指定されている必要がある。A CLS-compliant literal must have a value specified in field initialization metadata that is of exactly the same type as the literal (or of the underlying type, if that literal is an enum). 1313
メンバーMembers 一般的な型メンバーType members in general vararg 制約は CLS の一部ではなく、CLS でサポートする呼び出し規則だけが標準のマネージド呼び出し規則である。The vararg constraint is not part of the CLS, and the only calling convention supported by the CLS is the standard managed calling convention. 1515
名前付け規則Naming conventions 名前付け規則Naming conventions アセンブリは、識別子の頭文字および構成文字として使用できる文字セットを規定する Unicode Standard 3.0 の『Technical Report 15』の「Annex 7」に従う必要がある。詳細については、「https://www.unicode.org/unicode/reports/tr15/tr15-18.html」を参照。Assemblies shall follow Annex 7 of Technical Report 15 of the Unicode Standard3.0 governing the set of characters permitted to start and be included in identifiers, available online at https://www.unicode.org/unicode/reports/tr15/tr15-18.html. 識別子は、Unicode 正規形 C に定義されている標準形式で記述する必要がある。CLS で 2 つの識別子が同じと見なされるのは、小文字マッピング (Unicode のロケール非依存で 1 対 1 の小文字による対応付け) が同じ場合である。Identifiers shall be in the canonical format defined by Unicode Normalization Form C. For CLS purposes, two identifiers are the same if their lowercase mappings (as specified by the Unicode locale-insensitive, one-to-one lowercase mappings) are the same. つまり、CLS で 2 つの識別子が異なる場合、大文字小文字の違いだけではない。That is, for two identifiers to be considered different under the CLS they shall differ in more than simply their case. ただし、継承された定義をオーバーライドする場合、CLI では元の宣言と厳密に同じエンコーディングの使用が求められる。However, in order to override an inherited definition the CLI requires the precise encoding of the original declaration be used. 44
オーバーロードOverloading 名前付け規則Naming conventions CLS 準拠のスコープに導入されるすべての名前は、完全に独立した種類である必要があります。ただし、名前が同じでオーバーロードによって解決できる場合を除きます。All names introduced in a CLS-compliant scope shall be distinct independent of kind, except where the names are identical and resolved via overloading. CTS では 1 つの型でメソッドとフィールドとに同じ名前を使用できるが、CLS では使用できない。That is, while the CTSallows a single type to use the same name for a method and a field, the CLS does not. 55
オーバーロードOverloading 名前付け規則Naming conventions フィールドおよび入れ子になった型について、CTS ではシグネチャでの区別が可能だが、CLS では識別子の比較だけで区別できる必要がある。Fields and nested types shall be distinct by identifier comparison alone, even though the CTS allows distinct signatures to be distinguished. CLS 規則 39 の指定を除き、識別子の比較により名前が同じであるメソッド、プロパティ、およびイベントでは、相違点は戻り値の型だけに限定されない。Methods, properties, and events that have the same name (by identifier comparison) shall differ by more than just the return type,except as specified in CLS Rule 39. 66
オーバーロードOverloading OverloadsOverloads プロパティおよびメソッドのみオーバーロードできる。Only properties and methods can be overloaded. 3737
オーバーロードOverloading OverloadsOverloads プロパティおよびメソッドは、パラメーターの数値と型にのみ基づいてオーバーロードできる。ただし、戻り値の型に基づいてオーバーロードできる変換演算子の op_Implicit と oop_Explicit は例外である。Properties and methods can be overloaded based only on the number and types of their parameters, except the conversion operators named op_Implicit and op_Explicit, which can also be overloaded based on their return type. 3838
オーバーロードOverloading -- 型で宣言された複数の CLS 準拠のメソッドに同じ名前が指定されている場合、特定の一連の型のインスタンス化において、これらのメソッドのパラメーターと戻り値の型は同じである。また、これらの型のインスタンス化で、すべてのメソッドをセマンティクス レベルで等価にする必要がある。If two or more CLS-compliant methods declared in a type have the same name and, for a specific set of type instantiations, they have the same parameter and return types, then all these methods shall be semantically equivalent at those type instantiations. 4848
種類Types 型および型メンバーのシグネチャType and type member signatures System.Object は CLS 準拠である。System.Object is CLS-compliant. これ以外のあらゆる CLS 準拠クラスは CLS 準拠クラスの継承でなければならない。Any other CLS-compliant class shall inherit from a CLS-compliant class. 2323
プロパティProperties プロパティProperties プロパティの getter メソッドおよび setter メソッドを実装するメソッドは、メタデータで SpecialName とマークする。The methods that implement the getter and setter methods of a property shall be marked SpecialName in the metadata. 2424
プロパティProperties プロパティProperties プロパティ アクセサーはすべて静的、すべて仮想、またはすべてインスタンスになる。A property’s accessors shall all be static, all be virtual, or all be instance. 2626
プロパティProperties プロパティProperties プロパティの型は、getter の戻り値の型であり、かつ setter の最後の引数の型でなければいけない。The type of a property shall be the return type of the getter and the type of the last argument of the setter. プロパティのパラメーターの型は、getter へのパラメーターの型であり、かつ setter の最後のパラメーター以外のすべての型でなければいけない。The types of the parameters of the property shall be the types of the parameters to the getter and the types of all but the final parameter of the setter. すべての型は CLS 準拠でなければならない。また、マネージド ポインターであってはいけない。つまり、参照渡しではいけない。All of these types shall be CLS-compliant, and shall not be managed pointers (i.e., shall not be passed by reference). 2727
プロパティProperties プロパティProperties プロパティは、特定の名前付けパターンに従わなくてはいけない。Properties shall adhere to a specific naming pattern. CLS 規則 24 で触れられている SpecialName 属性は、適切な名前比較で無視され、識別子規則に従わなければいけない。The SpecialName attribute referred to in CLS rule 24 shall be ignored in appropriate name comparisons and shall adhere to identifier rules. プロパティには getter メソッド、setter メソッド、またはこの両方が必ずなければいけない。A property shall have a getter method, a setter method, or both. 2828
型変換Type conversion 型変換Type conversion op_Implicit または op_Explicit が指定されている場合は、強制変換のための別の方法を用意する必要がある。If either op_Implicit or op_Explicit is provided, an alternate means of providing the coercion shall be provided. 3939
種類Types 型および型メンバーのシグネチャType and type member signatures ボックス化された値型は CLS 準拠ではない。Boxed value types are not CLS-compliant. 33
種類Types 型および型メンバーのシグネチャType and type member signatures シグネチャに出現するすべての型は CLS 準拠でなければいけない。All types appearing in a signature shall be CLS-compliant. ジェネリック型のインスタンスを構成するすべての型は CLS 準拠でなければいけない。All types composing an instantiated generic type shall be CLS-compliant. 1111
種類Types 型および型メンバーのシグネチャType and type member signatures 型指定された参照は CLS 準拠ではありません。Typed references are not CLS-compliant. 1414
種類Types 型および型メンバーのシグネチャType and type member signatures アンマネージ ポインター型は CLS 準拠ではない。Unmanaged pointer types are not CLS-compliant. 1717
種類Types 型および型メンバーのシグネチャType and type member signatures CLS 準拠のクラス、値型、およびインターフェイスでは、CLS に準拠しないメンバーの実装は不要である。CLS-compliant classes, value types, and interfaces shall not require the implementation of non-CLS-compliant members. 2020

型および型メンバーのシグネチャTypes and type member signatures

System.Object 型は CLS に準拠しており、.NET Framework 型システムのすべてのオブジェクト型の基本型です。The System.Object type is CLS-compliant and is the base type of all object types in the .NET Framework type system. .NET Framework の継承は暗黙的また明示的に行われます。たとえば、String クラスは Object クラスから暗黙的に継承します。また、CultureNotFoundException クラスは、ArgumentException クラスから明示的に継承し、これは SystemException クラスから明示的に継承します。そして、このクラスは Exception クラスから明示的に継承します。Inheritance in the .NET Framework is either implicit (for example, the String class implicitly inherits from the Object class) or explicit (for example, the CultureNotFoundException class explicitly inherits from the ArgumentException class, which explicitly inherits from the SystemException class, which explicitly inherits from the Exception class). 派生型を CLS 準拠にするには、その基本型も CLS に準拠している必要があります。For a derived type to be CLS compliant, its base type must also be CLS-compliant.

次の例は、基本型が CLS に準拠していない派生型を示しています。The following example shows a derived type whose base type is not CLS-compliant. これは、符号なし 32 ビット整数をカウンターとして使用する Counter 基底クラスを定義します。It defines a base Counter class that uses an unsigned 32-bit integer as a counter. クラスには、符号なし整数をラップすることでカウンター機能が用意されます。このため、クラスは CLS 非準拠としてマークされます。Because the class provides counter functionality by wrapping an unsigned integer, the class is marked as non-CLS-compliant. 結果として、派生クラス NonZeroCounter も CLS に準拠しなくなります。As a result, a derived class, NonZeroCounter, is also not CLS-compliant.

using System;

[assembly: CLSCompliant(true)]

[CLSCompliant(false)] 
public class Counter
{
   UInt32 ctr;
   
   public Counter()
   {
      ctr = 0;
   }
   
   protected Counter(UInt32 ctr)
   {
      this.ctr = ctr;
   }
   
   public override string ToString()
   {
      return String.Format("{0}). ", ctr);
   }

   public UInt32 Value
   {
      get { return ctr; }
   }
   
   public void Increment() 
   {
      ctr += (uint) 1;
   }
}

public class NonZeroCounter : Counter
{
   public NonZeroCounter(int startIndex) : this((uint) startIndex)
   {
   }
   
   private NonZeroCounter(UInt32 startIndex) : base(startIndex)
   {
   }
}
// Compilation produces a compiler warning like the following:
//    Type3.cs(37,14): warning CS3009: 'NonZeroCounter': base type 'Counter' is not
//            CLS-compliant
//    Type3.cs(7,14): (Location of symbol related to previous warning)
<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> _ 
Public Class Counter
   Dim ctr As UInt32
   
   Public Sub New
      ctr = 0
   End Sub
   
   Protected Sub New(ctr As UInt32)
      ctr = ctr
   End Sub
   
   Public Overrides Function ToString() As String
      Return String.Format("{0}). ", ctr)
   End Function

   Public ReadOnly Property Value As UInt32
      Get
         Return ctr
      End Get
   End Property
   
   Public Sub Increment()
      ctr += CType(1, UInt32)
   End Sub
End Class

Public Class NonZeroCounter : Inherits Counter
   Public Sub New(startIndex As Integer)
      MyClass.New(CType(startIndex, UInt32))
   End Sub
   
   Private Sub New(startIndex As UInt32)
      MyBase.New(CType(startIndex, UInt32))
   End Sub
End Class
' Compilation produces a compiler warning like the following:
'    Type3.vb(34) : warning BC40026: 'NonZeroCounter' is not CLS-compliant 
'    because it derives from 'Counter', which is not CLS-compliant.
'    
'    Public Class NonZeroCounter : Inherits Counter
'                 ~~~~~~~~~~~~~~

メソッドの戻り値の型、プロパティ型を含め、メンバー シグネチャに表示されるすべての型が CLS に準拠する必要があります。All types that appear in member signatures, including a method's return type or a property type, must be CLS-compliant. さらに、ジェネリック型の場合は、次の要件もあります。In addition, for generic types:

  • ジェネリック型のインスタンスを構成するすべての型が、CLS に準拠する必要があります。All types that compose an instantiated generic type must be CLS-compliant.

  • ジェネリック パラメーターで制約として使用されるすべての型が、CLS に準拠する必要があります。All types used as constraints on generic parameters must be CLS-compliant.

.NET Framework の共通型システムには、共通言語ランタイムが直接サポートする組み込み型がいくつか含まれ、アセンブリのメタデータで特別にエンコードされています。The .NET Framework common type system includes a number of built-in types that are supported directly by the common language runtime and are specially encoded in an assembly's metadata. これらの組み込み型のうち、次の表に示す型は CLS に準拠しています。Of these intrinsic types, the types listed in the following table are CLS-compliant.

CLS 準拠型CLS-compliant type 説明Description
Byte 8 ビット符号なし整数8-bit unsigned integer
Int16 16 ビット符号付き整数16-bit signed integer
Int32 32 ビット符号付き整数32-bit signed integer
Int64 64 ビット符号付き整数64-bit signed integer
Single 単精度浮動小数点数値Single-precision floating-point value
Double 倍精度浮動小数点数値Double-precision floating-point value
Boolean true or false 値型true or false value type
Char UTF-16 でエンコードされたコード単位UTF-16 encoded code unit
Decimal 10 進浮動小数点数以外Non-floating-point decimal number
IntPtr プラットフォーム定義サイズのポインターまたはハンドルPointer or handle of a platform-defined size
String 0 個以上の Char オブジェクトのコレクションCollection of zero, one, or more Char objects

次の表に示す組み込み型は CLS に準拠していません。The intrinsic types listed in the following table are not CLS-Compliant.

非準拠型Non-compliant type 説明Description CLS に準拠する代替CLS-compliant alternative
SByte 8 ビット符号付き整数データ型8-bit signed integer data type Int16
TypedReference オブジェクトとそのランタイム型へのポインターPointer to an object and its runtime type なしNone
UInt16 16 ビット符号なし整数16-bit unsigned integer Int32
UInt32 32 ビット符号なし整数32-bit unsigned integer Int64
UInt64 64 ビット符号なし整数64-bit unsigned integer Int64 (オーバーフローの可能性あり)、BigInteger、または DoubleInt64 (may overflow), BigInteger, or Double
UIntPtr 符号なしポインターまたはハンドルUnsigned pointer or handle IntPtr

.NET Framework のクラス ライブラリまたはその他のクラス ライブラリには、CLS に準拠していない他の型が含まれる場合があります。次に例を示します。The .NET Framework Class Library or any other class library may include other types that aren't CLS-compliant; for example:

  • ボックス化された値型。Boxed value types. 次の C# コード例では、int* という名前の型 Value のパブリック プロパティを持つクラスを作成します。The following C# example creates a class that has a public property of type int* named Value. int* はボックス化された値型であるため、コンパイラは CLS 非準拠としてフラグを設定します。Because an int* is a boxed value type, the compiler flags it as non-CLS-compliant.

    using System;
    
    [assembly:CLSCompliant(true)]
    
    public unsafe class TestClass
    {
       private int* val;
       
       public TestClass(int number)
       {
          val = (int*) number;
       }
    
       public int* Value {
          get { return val; }        
       }
    }
    // The compiler generates the following output when compiling this example:
    //        warning CS3003: Type of 'TestClass.Value' is not CLS-compliant
    
  • 型指定された参照。オブジェクトへの参照および型への参照を含む特別なコンストラクトです。Typed references, which are special constructs that contain a reference to an object and a reference to a type. 型指定された参照は、.NET Framework では TypedReference クラスによって表されます。Typed references are represented in the .NET Framework by the TypedReference class.

型が CLS に準拠していない場合は、CLSCompliantAttribute 値が isCompliant に指定された false 属性を適用する必要があります。If a type is not CLS-compliant, you should apply the CLSCompliantAttribute attribute with an isCompliant value of false to it. 詳細については、「CLSCompliantAttribute 属性」を参照してください。For more information, see The CLSCompliantAttribute attribute section.

次の例は、メソッド シグネチャとジェネリック型のインスタンス化で発生する CLS 準拠の問題を示しています。The following example illustrates the problem of CLS compliance in a method signature and in generic type instantiation. ここでは、InvoiceItem クラスを、型 UInt32 のプロパティ、型 Nullable(Of UInt32) のプロパティ、および型 UInt32Nullable(Of UInt32) のパラメーターが指定されたコンストラクターで定義します。It defines an InvoiceItem class with a property of type UInt32, a property of type Nullable(Of UInt32), and a constructor with parameters of type UInt32 and Nullable(Of UInt32). この例をコンパイルしようとすると、4 つのコンパイラの警告が表示されます。You get four compiler warnings when you try to compile this example.

using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem
{
   private uint invId = 0;
   private uint itemId = 0;
   private Nullable<uint> qty;

   public InvoiceItem(uint sku, Nullable<uint> quantity)
   {
      itemId = sku;
      qty = quantity;
   }

   public Nullable<uint> Quantity
   {
      get { return qty; }
      set { qty = value; }
   }

   public uint InvoiceId
   {
      get { return invId; }
      set { invId = value; }
   }
}
// The attempt to compile the example displays the following output:
//    Type1.cs(13,23): warning CS3001: Argument type 'uint' is not CLS-compliant
//    Type1.cs(13,33): warning CS3001: Argument type 'uint?' is not CLS-compliant
//    Type1.cs(19,26): warning CS3003: Type of 'InvoiceItem.Quantity' is not CLS-compliant
//    Type1.cs(25,16): warning CS3003: Type of 'InvoiceItem.InvoiceId' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

   Private invId As UInteger = 0
   Private itemId As UInteger = 0
   Private qty AS Nullable(Of UInteger)
   
   Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
      itemId = sku
      qty = quantity
   End Sub

   Public Property Quantity As Nullable(Of UInteger)
      Get
         Return qty
      End Get   
      Set 
         qty = value
      End Set   
   End Property

   Public Property InvoiceId As UInteger
      Get   
         Return invId
      End Get
      Set 
         invId = value
      End Set   
   End Property
End Class
' The attempt to compile the example displays output similar to the following:
'    Type1.vb(13) : warning BC40028: Type of parameter 'sku' is not CLS-compliant.
'    
'       Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
'                      ~~~
'    Type1.vb(13) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'    
'       Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
'                                                               ~~~~~~~~
'    Type1.vb(18) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'    
'       Public Property Quantity As Nullable(Of UInteger)
'                                               ~~~~~~~~
'    Type1.vb(27) : warning BC40027: Return type of function 'InvoiceId' is not CLS-compliant.
'    
'       Public Property InvoiceId As UInteger
'                       ~~~~~~~~~

コンパイラの警告が表示されないようにするには、InvoiceItem パブリック インターフェイスの CLS 非準拠型を準拠型に置き換えます。To eliminate the compiler warnings, replace the non-CLS-compliant types in the InvoiceItem public interface with compliant types:

using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem
{
   private uint invId = 0;
   private uint itemId = 0;
   private Nullable<int> qty;

   public InvoiceItem(int sku, Nullable<int> quantity)
   {
      if (sku <= 0)
         throw new ArgumentOutOfRangeException("The item number is zero or negative.");
      itemId = (uint) sku;
      
      qty = quantity;
   }

   public Nullable<int> Quantity
   {
      get { return qty; }
      set { qty = value; }
   }

   public int InvoiceId
   {
      get { return (int) invId; }
      set { 
         if (value <= 0)
            throw new ArgumentOutOfRangeException("The invoice number is zero or negative.");
         invId = (uint) value; }
   }
}
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

   Private invId As UInteger = 0
   Private itemId As UInteger = 0
   Private qty AS Nullable(Of Integer)
   
   Public Sub New(sku As Integer, quantity As Nullable(Of Integer))
      If sku <= 0 Then
         Throw New ArgumentOutOfRangeException("The item number is zero or negative.")
      End If
      itemId = CUInt(sku)
      qty = quantity
   End Sub

   Public Property Quantity As Nullable(Of Integer)
      Get
         Return qty
      End Get   
      Set 
         qty = value
      End Set   
   End Property

   Public Property InvoiceId As Integer
      Get   
         Return CInt(invId)
      End Get
      Set 
         invId = CUInt(value)
      End Set   
   End Property
End Class

ここで示した特定の型以外にも、CLS に準拠していないカテゴリはいくつかあります。In addition to the specific types listed, some categories of types are not CLS compliant. たとえば、アンマネージ ポインター型やアンマネージ関数ポインター型などです。These include unmanaged pointer types and function pointer types. 次の例では、整数へのポインターを使用して整数の配列を作成するので、コンパイラの警告が生成されます。The following example generates a compiler warning because it uses a pointer to an integer to create an array of integers.

using System;

[assembly: CLSCompliant(true)]

public class ArrayHelper
{
   unsafe public static Array CreateInstance(Type type, int* ptr, int items)
   {
      Array arr = Array.CreateInstance(type, items);
      int* addr = ptr;
      for (int ctr = 0; ctr < items; ctr++) {
          int value = *addr;
          arr.SetValue(value, ctr);
          addr++;
      }
      return arr;
   }
}   
// The attempt to compile this example displays the following output:
//    UnmanagedPtr1.cs(8,57): warning CS3001: Argument type 'int*' is not CLS-compliant

CLS 準拠の抽象クラス (つまり、abstract (C# の場合) または MustInherit (Visual Basic の場合) とマークされたクラス) については、そのクラスのすべてのメンバーも CLS に準拠にする必要があります。For CLS-compliant abstract classes (that is, classes marked as abstract in C# or as MustInherit in Visual Basic), all members of the class must also be CLS-compliant.

名前付け規則Naming conventions

一部のプログラミング言語は大文字と小文字が区別されるので、識別子 (名前空間、型、メンバーの名前など) は、大文字と小文字が違うだけで相違します。Because some programming languages are case-insensitive, identifiers (such as the names of namespaces, types, and members) must differ by more than case. 2 つの識別子が同じと見なされるのは、小文字マッピングが同じ場合です。Two identifiers are considered equivalent if their lowercase mappings are the same. 次の C# コード例では、2 つのパブリック クラス、Person および person を定義します。The following C# example defines two public classes, Person and person. このクラスは大文字と小文字のみが異なるので、コンパイラは CLS 非準拠としてフラグを設定します。Because they differ only by case, the C# compiler flags them as not CLS-compliant.

using System;

[assembly: CLSCompliant(true)]

public class Person : person
{
 
}

public class person
{
 
}
// Compilation produces a compiler warning like the following:
//    Naming1.cs(11,14): warning CS3005: Identifier 'person' differing 
//                       only in case is not CLS-compliant
//    Naming1.cs(6,14): (Location of symbol related to previous warning)

名前空間、型、メンバーの名前など、プログラミング言語の識別子は Unicode Standard 3.0 の Technical Report 15 の Annex 7 に準拠する必要があります。Programming language identifiers, such as the names of namespaces, types, and members, must conform to the Unicode Standard 3.0, Technical Report 15, Annex 7. これによって、次のことが起こります。This means that:

  • 識別子の最初の文字は Unicode の大文字と小文字、大文字と小文字の組み合わせ、修飾子文字、その他の文字、または文字数の番号を指定できます。The first character of an identifier can be any Unicode uppercase letter, lowercase letter, title case letter, modifier letter, other letter, or letter number. Unicode 文字のカテゴリの詳細については、「System.Globalization.UnicodeCategory 列挙体」を参照してください。For information on Unicode character categories, see the System.Globalization.UnicodeCategory enumeration.

  • 2 文字目以降には、最初の文字で使用できる文字のほかに、非空白記号、空白結合記号、10 進数、接続符号、書式指定コードを使用できます。Subsequent characters can be from any of the categories as the first character, and can also include non-spacing marks, spacing combining marks, decimal numbers, connector punctuations, and formatting codes.

識別子を比較する場合は、その前に書式設定コードを除外してから、識別子を Unicode 正規形 C に変換する必要があります。これは 1 つの文字を、UTF-16 でエンコードされた複数のコード単位で表すことができるからです。Before you compare identifiers, you should filter out formatting codes and convert the identifiers to Unicode Normalization Form C, because a single character can be represented by multiple UTF-16-encoded code units. 同じコード単位を Unicode 正規形 C で生成する文字シーケンスは CLS に準拠していません。Character sequences that produce the same code units in Unicode Normalization Form C are not CLS-compliant. 次の例では、最初にオングストローム文字 (U+212B) である という名前のプロパティを定義し、次に、上に丸が付く LATIN の大文字 A (U+00C5) である Å という名前のプロパティを定義します。The following example defines a property named , which consists of the character ANGSTROM SIGN (U+212B), and a second property named Å, which consists of the character LATIN CAPITAL LETTER A WITH RING ABOVE (U+00C5). C# と Visual Basic の両方のコンパイラが、CLS 非準拠としてソース コードにフラグを設定します。Both the C# and Visual Basic compilers flag the source code as non-CLS-compliant.

public class Size
{
   private double a1;
   private double a2;
   
   public double Å
   {
       get { return a1; }
       set { a1 = value; }
   }         
         
   public double Å
   {
       get { return a2; }
       set { a2 = value; }
   }
}
// Compilation produces a compiler warning like the following:
//    Naming2a.cs(16,18): warning CS3005: Identifier 'Size.Å' differing only in case is not
//            CLS-compliant
//    Naming2a.cs(10,18): (Location of symbol related to previous warning)
//    Naming2a.cs(18,8): warning CS3005: Identifier 'Size.Å.get' differing only in case is not
//            CLS-compliant
//    Naming2a.cs(12,8): (Location of symbol related to previous warning)
//    Naming2a.cs(19,8): warning CS3005: Identifier 'Size.Å.set' differing only in case is not
//            CLS-compliant
//    Naming2a.cs(13,8): (Location of symbol related to previous warning)
<Assembly: CLSCompliant(True)>
Public Class Size
   Private a1 As Double
   Private a2 As Double
   
   Public Property Å As Double
       Get
          Return a1
       End Get
       Set 
          a1 = value
       End Set
   End Property         
         
   Public Property Å As Double
       Get
          Return a2
       End Get
       Set
          a2 = value
       End Set   
   End Property
End Class
' Compilation produces a compiler warning like the following:
'    Naming1.vb(9) : error BC30269: 'Public Property Å As Double' has multiple definitions
'     with identical signatures.
'    
'       Public Property Å As Double
'                       ~

特定のスコープ内のメンバー名 (アセンブリ内の名前空間、名前空間内の型、型内のメンバーなど) は一意である必要があります。ただし、オーバーロードによって解決される名前は除きます。Member names within a particular scope (such as the namespaces within an assembly, the types within a namespace, or the members within a type) must be unique except for names that are resolved through overloading. この要件は、共通型システムの要件よりも厳格です。共通型システムでは、スコープ内のメンバーは種類が異なっていれば、たとえば、種類がメソッドのメンバーとフィールドのメンバーは、同じ名前を持つことができます。This requirement is more stringent than that of the common type system, which allows multiple members within a scope to have identical names as long as they are different kinds of members (for example, one is a method and one is a field). 特に、型メンバーの場合は次の要件もあります。In particular, for type members:

  • フィールドと入れ子になった型は名前でのみ識別されます。Fields and nested types are distinguished by name alone.

  • 名前が同じメソッド、プロパティ、およびイベントは、戻り値の型以外で区別できるようにする必要があります。Methods, properties, and events that have the same name must differ by more than just return type.

次の例は、メンバー名がスコープ内で一意でなければならない要件を示しています。The following example illustrates the requirement that member names must be unique within their scope. ここでは、Converter という名前の 4 つのメンバーを含む Conversion という名前のクラスを定義します。It defines a class named Converter that includes four members named Conversion. 3 つがメソッドで、1 つはプロパティです。Three are methods, and one is a property. Int64 パラメーターを含むメソッドには一意の名前が付けられますが、Int32 パラメーターが指定された 2 つのメソッドには一意の名前は付けられません。これは戻り値がメンバーのシグネチャの一部と見なされないからです。The method that includes an Int64 parameter is uniquely named, but the two methods with an Int32 parameter are not, because return value is not considered a part of a member's signature. また、Conversion プロパティもこの要件に違反しています。プロパティの名前は、オーバーロードされたメソッドと同じにできないからです。The Conversion property also violates this requirement, because properties cannot have the same name as overloaded methods.

using System;

[assembly: CLSCompliant(true)]

public class Converter
{
   public double Conversion(int number)
   {
      return (double) number;
   }

   public float Conversion(int number)
   {
      return (float) number;
   }
   
   public double Conversion(long number)
   {
      return (double) number;
   }
   
   public bool Conversion
   {
      get { return true; }
   }     
}  
// Compilation produces a compiler error like the following:
//    Naming3.cs(13,17): error CS0111: Type 'Converter' already defines a member called
//            'Conversion' with the same parameter types
//    Naming3.cs(8,18): (Location of symbol related to previous error)
//    Naming3.cs(23,16): error CS0102: The type 'Converter' already contains a definition for
//            'Conversion'
//    Naming3.cs(8,18): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

Public Class Converter
   Public Function Conversion(number As Integer) As Double
      Return CDbl(number)
   End Function

   Public Function Conversion(number As Integer) As Single
      Return CSng(number)
   End Function
   
   Public Function Conversion(number As Long) As Double
      Return CDbl(number)
   End Function
   
   Public ReadOnly Property Conversion As Boolean
      Get
         Return True
      End Get   
   End Property     
End Class
' Compilation produces a compiler error like the following:
'    Naming3.vb(8) : error BC30301: 'Public Function Conversion(number As Integer) As Double' 
'                    and 'Public Function Conversion(number As Integer) As Single' cannot 
'                    overload each other because they differ only by return types.
'    
'       Public Function Conversion(number As Integer) As Double
'                       ~~~~~~~~~~
'    Naming3.vb(20) : error BC30260: 'Conversion' is already declared as 'Public Function 
'                     Conversion(number As Integer) As Single' in this class.
'    
'       Public ReadOnly Property Conversion As Boolean
'                                ~~~~~~~~~~

個々の言語に一意のキーワードが含まれるので、共通言語ランタイムを対象にする言語も、キーワードと一致する識別子 (型名など) を参照するための機構を用意する必要があります。Individual languages include unique keywords, so languages that target the common language runtime must also provide some mechanism for referencing identifiers (such as type names) that coincide with keywords. たとえば、case は、C# と Visual Basic のキーワードです。For example, case is a keyword in both C# and Visual Basic. ただし、次の Visual Basic コード例では、左右の中かっこを使用して、case キーワードと case という名前のクラスを明確に区別できます。However, the following Visual Basic example is able to disambiguate a class named case from the case keyword by using opening and closing braces. それ以外の場合は、エラー メッセージ "キーワードは、識別子として有効ではありません" が表示され、コンパイルできません。Otherwise, the example would produce the error message, "Keyword is not valid as an identifier," and fail to compile.

Public Class [case]
   Private _id As Guid
   Private name As String  
   
   Public Sub New(name As String)
      _id = Guid.NewGuid()
      Me.name = name 
   End Sub   
        
   Public ReadOnly Property ClientName As String
      Get
         Return name
      End Get
   End Property
End Class

次の C# コード例では、case シンボルを使用して @ クラスをインスタンス化することで、識別子と言語キーワードを区別できます。The following C# example is able to instantiate the case class by using the @ symbol to disambiguate the identifier from the language keyword. これがないと、C# コンパイラによって 2 つのエラー メッセージ "型が必要です" および "'case' は無効です" が表示されます。Without it, the C# compiler would display two error messages, "Type expected" and "Invalid expression term 'case'."

using System;

public class Example
{
   public static void Main()
   {
      @case c = new @case("John");
      Console.WriteLine(c.ClientName);
   }
}

型変換Type conversion

共通言語仕様では、次の 2 つの変換演算子が定義されます。The Common Language Specification defines two conversion operators:

  • op_Implicit。データまたは精度の損失につながらない拡大変換に使用されます。op_Implicit, which is used for widening conversions that do not result in loss of data or precision. たとえば、Decimal 構造体には、整数型の値と op_Implicit 値を Char 値に変換できるように、オーバーロードされた Decimal 演算子が含まれます。For example, the Decimal structure includes an overloaded op_Implicit operator to convert values of integral types and Char values to Decimal values.

  • op_Explicit。絶対値 (狭い範囲の値に変換される値) または精度の損失につながる可能性がある縮小変換に使用されます。op_Explicit, which is used for narrowing conversions that can result in loss of magnitude (a value is converted to a value that has a smaller range) or precision. たとえば、Decimal 構造体には、op_Explicit 値と Double 値を Single に変換し、Decimal 値を整数値、DecimalDouble、および Single に変換できるように、オーバーロードされた Char 演算子が含まれます。For example, the Decimal structure includes an overloaded op_Explicit operator to convert Double and Single values to Decimal and to convert Decimal values to integral values, Double, Single, and Char.

ただし、すべての言語で、演算子のオーバーロードまたはカスタム演算子の定義がサポートされているわけではありません。However, not all languages support operator overloading or the definition of custom operators. これらの変換演算子を実装する場合は、他の方法で変換を実行する方法も用意する必要があります。If you choose to implement these conversion operators, you should also provide an alternate way to perform the conversion. ここでは、FromXxx メソッドと ToXxx メソッドを用意することをお勧めします。We recommend that you provide FromXxx and ToXxx methods.

次の例では、CLS に準拠する暗黙的な変換と明示的な変換を定義します。The following example defines CLS-compliant implicit and explicit conversions. ここでは、符号付き倍精度浮動小数点数を表す UDouble クラスを作成します。It creates a UDouble class that represents an signed double-precision, floating-point number. 暗黙的な変換については、UDouble から Double、明示的な変換については、UDouble から SingleDouble から UDouble、および Single から UDouble への例を示しています。It provides for implicit conversions from UDouble to Double and for explicit conversions from UDouble to Single, Double to UDouble, and Single to UDouble. また、暗黙的な変換演算子の代替として ToDouble メソッドを、明示的な変換演算子の代替として ToSingleFromDoubleFromSingle の各メソッドを定義します。It also defines a ToDouble method as an alternative to the implicit conversion operator and the ToSingle, FromDouble, and FromSingle methods as alternatives to the explicit conversion operators.

using System;

public struct UDouble
{
   private double number;
   
   public UDouble(double value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      number = value;
   }
   
   public UDouble(float value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      number = value;
   }
   
   public static readonly UDouble MinValue = (UDouble) 0.0;
   public static readonly UDouble MaxValue = (UDouble) Double.MaxValue;
   
   public static explicit operator Double(UDouble value)
   {
      return value.number;
   }
   
   public static implicit operator Single(UDouble value)
   {
      if (value.number > (double) Single.MaxValue) 
         throw new InvalidCastException("A UDouble value is out of range of the Single type.");

      return (float) value.number;         
   }
   
   public static explicit operator UDouble(double value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      return new UDouble(value);
   } 

   public static implicit operator UDouble(float value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      return new UDouble(value);
   } 

   public static Double ToDouble(UDouble value)
   {
      return (Double) value;
   }   

   public static float ToSingle(UDouble value)
   {
      return (float) value;
   }   

   public static UDouble FromDouble(double value)
   {
      return new UDouble(value);
   }
   
   public static UDouble FromSingle(float value)
   {
      return new UDouble(value);
   }   
}
Public Structure UDouble
   Private number As Double
   
   Public Sub New(value As Double)
      If value < 0 Then
         Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
      End If
      number = value
   End Sub
   
   Public Sub New(value As Single)
      If value < 0 Then
         Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
      End If
      number = value
   End Sub
   
   Public Shared ReadOnly MinValue As UDouble = CType(0.0, UDouble)
   Public Shared ReadOnly MaxValue As UDouble = Double.MaxValue
   
   Public Shared Widening Operator CType(value As UDouble) As Double
      Return value.number
   End Operator
   
   Public Shared Narrowing Operator CType(value As UDouble) As Single
      If value.number > CDbl(Single.MaxValue) Then
         Throw New InvalidCastException("A UDouble value is out of range of the Single type.")
      End If
      Return CSng(value.number)         
   End Operator
   
   Public Shared Narrowing Operator CType(value As Double) As UDouble
      If value < 0 Then
         Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
      End If
      Return New UDouble(value)
   End Operator 

   Public Shared Narrowing Operator CType(value As Single) As UDouble
      If value < 0 Then
         Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
      End If
      Return New UDouble(value)
   End Operator 

   Public Shared Function ToDouble(value As UDouble) As Double
      Return CType(value, Double)
   End Function   

   Public Shared Function ToSingle(value As UDouble) As Single
      Return CType(value, Single)
   End Function   

   Public Shared Function FromDouble(value As Double) As UDouble
      Return New UDouble(value)
   End Function
   
   Public Shared Function FromSingle(value As Single) As UDouble
      Return New UDouble(value)
   End Function   
End Structure

配列Arrays

CLS 準拠の配列は、次の規則に従います。CLS-compliant arrays conform to the following rules:

  • 配列の次元の下限値は 0 にする必要があります。All dimensions of an array must have a lower bound of zero. 次の例では、下限が 1 の CLS 非準拠の配列を作成します。The following example creates a non-CLS-compliant array with a lower bound of one. CLSCompliantAttribute 属性の有無に関係なく、コンパイラでは、Numbers.GetTenPrimes メソッドによって返される配列が CLS に準拠していないことは検出されません。Note that, despite the presence of the CLSCompliantAttribute attribute, the compiler does not detect that the array returned by the Numbers.GetTenPrimes method is not CLS-compliant.

    [assembly: CLSCompliant(true)]
    
    public class Numbers
    {
       public static Array GetTenPrimes()
       {
          Array arr = Array.CreateInstance(typeof(Int32), new int[] {10}, new int[] {1});
          arr.SetValue(1, 1);
          arr.SetValue(2, 2);
          arr.SetValue(3, 3);
          arr.SetValue(5, 4);
          arr.SetValue(7, 5);
          arr.SetValue(11, 6);
          arr.SetValue(13, 7);
          arr.SetValue(17, 8);
          arr.SetValue(19, 9);
          arr.SetValue(23, 10);
    
          return arr; 
       }
    }
    
    <Assembly: CLSCompliant(True)>
    
    Public Class Numbers
       Public Shared Function GetTenPrimes() As Array
          Dim arr As Array = Array.CreateInstance(GetType(Int32), {10}, {1})
          arr.SetValue(1, 1)
          arr.SetValue(2, 2)
          arr.SetValue(3, 3)
          arr.SetValue(5, 4)
          arr.SetValue(7, 5)
          arr.SetValue(11, 6)
          arr.SetValue(13, 7)
          arr.SetValue(17, 8)
          arr.SetValue(19, 9)
          arr.SetValue(23, 10)
          
          Return arr
       End Function
    End Class
    
  • すべての配列の要素が、CLS 準拠の型で構成されている必要があります。All array elements must consist of CLS-compliant types. 次の例では、CLS 非準拠の配列を返す 2 つのメソッドを定義します。The following example defines two methods that return non-CLS-compliant arrays. 最初のメソッドは、UInt32 値の配列を返します。The first returns an array of UInt32 values. 2 番目のメソッドは Object 値と Int32 値を含む UInt32 配列を返します。The second returns an Object array that includes Int32 and UInt32 values. 最初の配列は UInt32 型であるため、コンパイラによって非準拠として識別されますが、2 番目の配列に CLS 非準拠の要素が含まれていることは認識されません。Although the compiler identifies the first array as non-compliant because of its UInt32 type, it fails to recognize that the second array includes non-CLS-compliant elements.

    using System;
    
    [assembly: CLSCompliant(true)]
    
    public class Numbers
    {
       public static UInt32[] GetTenPrimes()
       {
          uint[] arr = { 1u, 2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u };
          return arr;
       }
       
       public static Object[] GetFivePrimes()
       {
          Object[] arr = { 1, 2, 3, 5u, 7u };
          return arr;
       }
    }
    // Compilation produces a compiler warning like the following:
    //    Array2.cs(8,27): warning CS3002: Return type of 'Numbers.GetTenPrimes()' is not
    //            CLS-compliant
    
    <Assembly: CLSCompliant(True)>
    
    Public Class Numbers
       Public Shared Function GetTenPrimes() As UInt32()
          Return { 1ui, 2ui, 3ui, 5ui, 7ui, 11ui, 13ui, 17ui, 19ui }
       End Function
       
       Public Shared Function GetFivePrimes() As Object()
          Dim arr() As Object = { 1, 2, 3, 5ui, 7ui }
          Return arr
       End Function
    End Class
    ' Compilation produces a compiler warning like the following:
    '    warning BC40027: Return type of function 'GetTenPrimes' is not CLS-compliant.
    '    
    '       Public Shared Function GetTenPrimes() As UInt32()
    '                              ~~~~~~~~~~~~
    
  • 配列パラメーターを持つメソッドのオーバーロードの解決は、配列であるという事実とその要素型に基づきます。Overload resolution for methods that have array parameters is based on the fact that they are arrays and on their element type. したがって、次のオーバーロードされた GetSquares メソッドの定義は CLS に準拠しています。For this reason, the following definition of an overloaded GetSquares method is CLS-compliant.

    using System;
    using System.Numerics;
    
    [assembly: CLSCompliant(true)]
    
    public class Numbers
    {
       public static byte[] GetSquares(byte[] numbers)
       {
          byte[] numbersOut = new byte[numbers.Length];
          for (int ctr = 0; ctr < numbers.Length; ctr++) {
             int square = ((int) numbers[ctr]) * ((int) numbers[ctr]); 
             if (square <= Byte.MaxValue)
                numbersOut[ctr] = (byte) square;
             // If there's an overflow, assign MaxValue to the corresponding 
             // element.
             else
                numbersOut[ctr] = Byte.MaxValue;
    
          }
          return numbersOut;
       }
    
       public static BigInteger[] GetSquares(BigInteger[] numbers)
       {
          BigInteger[] numbersOut = new BigInteger[numbers.Length];
          for (int ctr = 0; ctr < numbers.Length; ctr++)
             numbersOut[ctr] = numbers[ctr] * numbers[ctr]; 
    
          return numbersOut;
       }
    }
    
    Imports System.Numerics
    
    <Assembly: CLSCompliant(True)>
    
    Public Module Numbers
       Public Function GetSquares(numbers As Byte()) As Byte()
          Dim numbersOut(numbers.Length - 1) As Byte
          For ctr As Integer = 0 To numbers.Length - 1
             Dim square As Integer = (CInt(numbers(ctr)) * CInt(numbers(ctr))) 
             If square <= Byte.MaxValue Then
                numbersOut(ctr) = CByte(square)
             ' If there's an overflow, assign MaxValue to the corresponding 
             ' element.
             Else
                numbersOut(ctr) = Byte.MaxValue
             End If   
          Next
          Return numbersOut
       End Function
    
       Public Function GetSquares(numbers As BigInteger()) As BigInteger()
          Dim numbersOut(numbers.Length - 1) As BigInteger
          For ctr As Integer = 0 To numbers.Length - 1
             numbersOut(ctr) = numbers(ctr) * numbers(ctr) 
          Next
          Return numbersOut
       End Function
    End Module
    

インターフェイスInterfaces

CLS 準拠のインターフェイスでは、プロパティ、イベント、および仮想メソッド (実装のないメソッド) を定義できます。CLS-compliant interfaces can define properties, events, and virtual methods (methods with no implementation). 次の項目は、このインターフェイスには指定できません。A CLS-compliant interface cannot have any of the following:

  • 静的メソッドまたは静的フィールド。Static methods or static fields. インターフェイスで静的メンバーを定義すると、C# と Visual Basic の両方のコンパイラでコンパイラ エラーが発生します。Both the C# and Visual Basic compilers generate compiler errors if you define a static member in an interface.

  • フィールド。Fields. インターフェイスでフィールドを定義すると、C# と Visual Basic の両方のコンパイラでコンパイラ エラーが発生します。Both the C# and Visual Basic compilers generate compiler errors if you define a field in an interface.

  • CLS に準拠していないメソッド。Methods that are not CLS-compliant. たとえば、次のインターフェイス定義には、CLS 非準拠とマークされているメソッド、INumber.GetUnsigned が含まれています。For example, the following interface definition includes a method, INumber.GetUnsigned, that is marked as non-CLS-compliant. この例では、コンパイラの警告が生成されます。This example generates a compiler warning.

    using System;
    
    [assembly:CLSCompliant(true)]
    
    public interface INumber
    {
       int Length();
       [CLSCompliant(false)] ulong GetUnsigned();
    }
    // Attempting to compile the example displays output like the following:
    //    Interface2.cs(8,32): warning CS3010: 'INumber.GetUnsigned()': CLS-compliant interfaces
    //            must have only CLS-compliant members
    
    <Assembly: CLSCompliant(True)>
    
    Public Interface INumber
       Function Length As Integer
       
       <CLSCompliant(False)> Function GetUnsigned As ULong   
    End Interface
    ' Attempting to compile the example displays output like the following:
    '    Interface2.vb(9) : warning BC40033: Non CLS-compliant 'function' is not allowed in a 
    '    CLS-compliant interface.
    '    
    '       <CLSCompliant(False)> Function GetUnsigned As ULong
    '                                      ~~~~~~~~~~~
    

    この規則のため、CLS に準拠している型は、CLS に準拠していないメンバーを実装する必要はありません。Because of this rule, CLS-compliant types are not required to implement non-CLS-compliant members. CLS 準拠のフレームワークによって、CLS に非準拠のインターフェイスを実装するクラスが公開されている場合、そのフレームワークには、CLS 非準拠のすべてのメンバーの具象実装も用意する必要があります。If a CLS-compliant framework does expose a class that implements a non-CLS compliant interface, it should also provide concrete implementations of all non-CLS-compliant members.

CLS 準拠の言語コンパイラでは、クラスによって、複数のインターフェイスにある同じ名前およびシグネチャを持つメンバーを個別に実装できるようにすることも必要です。CLS-compliant language compilers must also allow a class to provide separate implementations of members that have the same name and signature in multiple interfaces. C# と Visual Basic の両方が明示的なインターフェイス実装をサポートしており、同じ名前を持つメソッドを別々に実装できます。Both C# and Visual Basic support explicit interface implementations to provide different implementations of identically named methods. Visual Basic では Implements キーワードもサポートされているので、特定のメンバーが実装するインターフェイスおよびメンバーを明示的に指定できます。Visual Basic also supports the Implements keyword, which enables you to explicitly designate which interface and member a particular member implements. 次の例は、明示的なインターフェイス実装として Temperature インターフェイスおよび ICelsius インターフェイスを実装する IFahrenheit クラスを定義することで、このシナリオを示しています。The following example illustrates this scenario by defining a Temperature class that implements the ICelsius and IFahrenheit interfaces as explicit interface implementations.

using System;

[assembly: CLSCompliant(true)]

public interface IFahrenheit
{
   decimal GetTemperature();
}

public interface ICelsius
{
   decimal GetTemperature();
}

public class Temperature : ICelsius, IFahrenheit
{
   private decimal _value;
   
   public Temperature(decimal value)
   {
      // We assume that this is the Celsius value.
      _value = value;
   } 
   
   decimal IFahrenheit.GetTemperature()
   {
      return _value * 9 / 5 + 32;
   }

   decimal ICelsius.GetTemperature()
   {
      return _value;
   } 
}
public class Example
{
   public static void Main()
   {
      Temperature temp = new Temperature(100.0m);
      ICelsius cTemp = temp;
      IFahrenheit fTemp = temp;
      Console.WriteLine("Temperature in Celsius: {0} degrees", 
                        cTemp.GetTemperature());
      Console.WriteLine("Temperature in Fahrenheit: {0} degrees", 
                        fTemp.GetTemperature());
   }
}
// The example displays the following output:
//       Temperature in Celsius: 100.0 degrees
//       Temperature in Fahrenheit: 212.0 degrees
<Assembly: CLSCompliant(True)>

Public Interface IFahrenheit
   Function GetTemperature() As Decimal
End Interface
   
Public Interface ICelsius
   Function GetTemperature() As Decimal
End Interface

Public Class Temperature : Implements ICelsius, IFahrenheit
   Private _value As Decimal
   
   Public Sub New(value As Decimal)
      ' We assume that this is the Celsius value.
      _value = value
   End Sub 
   
   Public Function GetFahrenheit() As Decimal _
          Implements IFahrenheit.GetTemperature
      Return _value * 9 / 5 + 32
   End Function

   Public Function GetCelsius() As Decimal _
          Implements ICelsius.GetTemperature
      Return _value
   End Function 
End Class

Module Example
   Public Sub Main()
      Dim temp As New Temperature(100.0d)
      Console.WriteLine("Temperature in Celsius: {0} degrees", 
                        temp.GetCelsius())
      Console.WriteLine("Temperature in Fahrenheit: {0} degrees", 
                        temp.GetFahrenheit())
   End Sub
End Module
' The example displays the following output:
'       Temperature in Celsius: 100.0 degrees
'       Temperature in Fahrenheit: 212.0 degrees

列挙Enumerations

CLS 準拠の列挙型は、次の規則に従う必要があります。CLS-compliant enumerations must follow these rules:

  • 列挙体の基になる型は、組み込みの CLS 準拠の整数 (ByteInt16Int32、または Int64) である必要があります。The underlying type of the enumeration must be an intrinsic CLS-compliant integer (Byte, Int16, Int32, or Int64). たとえば、次のコードでは、基になる型が UInt32 の列挙体を定義しようとしますが、コンパイラの警告が生成されます。For example, the following code tries to define an enumeration whose underlying type is UInt32 and generates a compiler warning.

    using System;
    
    [assembly: CLSCompliant(true)]
    
    public enum Size : uint { 
       Unspecified = 0, 
       XSmall = 1, 
       Small = 2, 
       Medium = 3, 
       Large = 4, 
       XLarge = 5 
    };
    
    public class Clothing
    {
       public string Name; 
       public string Type;
       public string Size;
    }
    // The attempt to compile the example displays a compiler warning like the following:
    //    Enum3.cs(6,13): warning CS3009: 'Size': base type 'uint' is not CLS-compliant
    
    <Assembly: CLSCompliant(True)>
    
    Public Enum Size As UInt32
       Unspecified = 0
       XSmall = 1
       Small = 2
       Medium = 3
       Large = 4
       XLarge = 5
    End Enum
    
    Public Class Clothing
       Public Name As String
       Public Type As String
       Public Size As Size
    End Class
    ' The attempt to compile the example displays a compiler warning like the following:
    '    Enum3.vb(6) : warning BC40032: Underlying type 'UInt32' of Enum is not CLS-compliant.
    '    
    '    Public Enum Size As UInt32
    '                ~~~~
    
  • 列挙型には、Value__ 属性でマークされた FieldAttributes.RTSpecialName という名前の単一インスタンス フィールドが必要です。An enumeration type must have a single instance field named Value__ that is marked with the FieldAttributes.RTSpecialName attribute. これにより、フィールド値を暗黙的に参照できます。This enables you to reference the field value implicitly.

  • 列挙体には、その列挙体自体の型と同じ型を持つリテラルな静的フィールドが含まれます。An enumeration includes literal static fields whose types match the type of the enumeration itself. たとえば、State および State.On の値を持つ State.Off 列挙体を定義すると、State.OnState.Off は両方ともリテラルな静的フィールドで、その型は State です。For example, if you define a State enumeration with values of State.On and State.Off, State.On and State.Off are both literal static fields whose type is State.

  • 列挙体は 2 種類あります。There are two kinds of enumerations:

    • 同時に指定できない一連の名前付き整数値を表す列挙体。An enumeration that represents a set of mutually exclusive, named integer values. この列挙体の型は、System.FlagsAttribute カスタム属性が存在しないことによって示されます。This type of enumeration is indicated by the absence of the System.FlagsAttribute custom attribute.

    • 名前のない値を生成するために結合できる一連のビット フラグを表す列挙体。An enumeration that represents a set of bit flags that can combine to generate an unnamed value. この列挙体の型は、System.FlagsAttribute カスタム属性が存在することによって示されます。This type of enumeration is indicated by the presence of the System.FlagsAttribute custom attribute.

    詳細については、Enum 構造体のドキュメントを参照してください。For more information, see the documentation for the Enum structure.

  • 列挙体の値は、その列挙体の指定された値に限定されません。The value of an enumeration is not limited to the range of its specified values. つまり、列挙体の値の範囲は、その列挙体の基になる値の範囲です。In other words, the range of values in an enumeration is the range of its underlying value. Enum.IsDefined メソッドを使用すると、指定された値が列挙体のメンバーかどうかを確認できます。You can use the Enum.IsDefined method to determine whether a specified value is a member of an enumeration.

一般的な型メンバーType members in general

共通言語仕様では、すべてのフィールドとメソッドに、特定のクラスのメンバーとしてアクセスする必要があります。The Common Language Specification requires all fields and methods to be accessed as members of a particular class. したがって、グローバルな静的フィールドおよび静的メソッド (つまり、型とは別に定義された静的フィールドまたは静的メソッド) は CLS に準拠していません。Therefore, global static fields and methods (that is, static fields or methods that are defined apart from a type) are not CLS-compliant. グローバル フィールドまたはグローバル メソッドをソース コードに追加しようとすると、C# と Visual Basic の両方のコンパイラでコンパイラ エラーが発生します。If you try to include a global field or method in your source code, both the C# and Visual Basic compilers generate a compiler error.

共通言語仕様では、標準のマネージド呼び出し規約のみがサポートされます。The Common Language Specification supports only the standard managed calling convention. アンマネージ呼び出し規約と、varargs キーワードでマークされた可変個引数リストを持つメソッドはサポートされません。It doesn't support unmanaged calling conventions and methods with variable argument lists marked with the varargs keyword. 標準のマネージド呼び出し規約と互換性がある可変個引数リストについては、params キーワード (C# の場合)、ParamArray キーワード (Visual Basic の場合) など、ParamArrayAttribute 属性または個々の言語の実装を使用します。For variable argument lists that are compatible with the standard managed calling convention, use the ParamArrayAttribute attribute or the individual language's implementation, such as the params keyword in C# and the ParamArray keyword in Visual Basic.

メンバーのアクセシビリティMember accessibility

継承されたメンバーをオーバーライドしても、そのメンバーのアクセシビリティは変更できません。Overriding an inherited member cannot change the accessibility of that member. たとえば、基底クラスのパブリック メソッドは、派生クラスのプライベート メソッドではオーバーライドできません。For example, a public method in a base class cannot be overridden by a private method in a derived class. ただし例外が 1 つあります。あるアセンブリ内にある、別のアセンブリの型でオーバーライドされた protected internal メンバー (C# の場合) または Protected Friend メンバー (Visual Basic の場合) です。There is one exception: a protected internal (in C#) or Protected Friend (in Visual Basic) member in one assembly that is overridden by a type in a different assembly. この場合、オーバーライドのアクセシビリティは Protected です。In that case, the accessibility of the override is Protected.

次の例は、CLSCompliantAttribute 属性が true で、Human の派生クラス Animal が、Species プロパティのアクセシビリティをパブリックからプライベートに変更しようとするときに発生するエラーを示しています。The following example illustrates the error that is generated when the CLSCompliantAttribute attribute is set to true, and Human, which is a class derived from Animal, tries to change the accessibility of the Species property from public to private. アクセシビリティがパブリックに変更されると、コンパイルが正常に行われます。The example compiles successfully if its accessibility is changed to public.

using System;

[assembly: CLSCompliant(true)]

public class Animal
{
   private string _species;
   
   public Animal(string species)
   {
      _species = species;
   }
   
   public virtual string Species 
   {    
      get { return _species; }
   }
   
   public override string ToString()
   {
      return _species;   
   } 
}

public class Human : Animal
{
   private string _name;
   
   public Human(string name) : base("Homo Sapiens")
   {
      _name = name;
   }
   
   public string Name
   {
      get { return _name; }
   }
   
   private override string Species 
   {
      get { return base.Species; }
   }
   
   public override string ToString() 
   {
      return _name;
   }
}

public class Example
{
   public static void Main()
   {
      Human p = new Human("John");
      Console.WriteLine(p.Species);
      Console.WriteLine(p.ToString());
   }
}
// The example displays the following output:
//    error CS0621: 'Human.Species': virtual or abstract members cannot be private
<Assembly: CLSCompliant(True)>

Public Class Animal
   Private _species As String
   
   Public Sub New(species As String)
      _species = species
   End Sub
   
   Public Overridable ReadOnly Property Species As String
      Get
         Return _species
      End Get
   End Property
   
   Public Overrides Function ToString() As String
      Return _species   
   End Function 
End Class

Public Class Human : Inherits Animal
   Private _name As String
   
   Public Sub New(name As String)
      MyBase.New("Homo Sapiens")
      _name = name
   End Sub
   
   Public ReadOnly Property Name As String
      Get
         Return _name
      End Get
   End Property
   
   Private Overrides ReadOnly Property Species As String
      Get
         Return MyBase.Species
      End Get   
   End Property
   
   Public Overrides Function ToString() As String
      Return _name
   End Function
End Class

Public Module Example
   Public Sub Main()
      Dim p As New Human("John")
      Console.WriteLine(p.Species)
      Console.WriteLine(p.ToString())
   End Sub
End Module
' The example displays the following output:
'     'Private Overrides ReadOnly Property Species As String' cannot override 
'     'Public Overridable ReadOnly Property Species As String' because
'      they have different access levels.
' 
'         Private Overrides ReadOnly Property Species As String

メンバーにアクセスできる場合は必ず、そのメンバーのシグネチャの型にアクセスできなければなりません。Types in the signature of a member must be accessible whenever that member is accessible. たとえば、これは、パブリック メンバーには、型がプライベート、プロテクト、または内部のパラメーターを含められないことを意味します。For example, this means that a public member cannot include a parameter whose type is private, protected, or internal. 次の例は、StringWrapper クラス コンストラクターが、文字列値のラップ方法を決定する内部 StringOperationType 列挙値を公開した場合に発生するコンパイラ エラーを示しています。The following example illustrates the compiler error that results when a StringWrapper class constructor exposes an internal StringOperationType enumeration value that determines how a string value should be wrapped.

using System;
using System.Text;

public class StringWrapper
{
   string internalString;
   StringBuilder internalSB = null;
   bool useSB = false;
   
   public StringWrapper(StringOperationType type)
   {   
      if (type == StringOperationType.Normal) {
         useSB = false;
      }   
      else {
         useSB = true;
         internalSB = new StringBuilder();
      }    
   }
   
   // The remaining source code...
}

internal enum StringOperationType { Normal, Dynamic }
// The attempt to compile the example displays the following output:
//    error CS0051: Inconsistent accessibility: parameter type
//            'StringOperationType' is less accessible than method
//            'StringWrapper.StringWrapper(StringOperationType)'
Imports System.Text

<Assembly:CLSCompliant(True)>

Public Class StringWrapper
   
   Dim internalString As String
   Dim internalSB As StringBuilder = Nothing
   Dim useSB As Boolean = False
   
   Public Sub New(type As StringOperationType)   
      If type = StringOperationType.Normal Then
         useSB = False
      Else
         internalSB = New StringBuilder() 
         useSB = True
      End If    
   End Sub
   
   ' The remaining source code...
End Class

Friend Enum StringOperationType As Integer
   Normal = 0
   Dynamic = 1
End Enum
' The attempt to compile the example displays the following output:
'    error BC30909: 'type' cannot expose type 'StringOperationType'
'     outside the project through class 'StringWrapper'.
'    
'       Public Sub New(type As StringOperationType)
'                              ~~~~~~~~~~~~~~~~~~~

ジェネリック型とメンバーGeneric types and members

入れ子になった型には、少なくともその外側の型と同じ数のジェネリック パラメーターが必要です。Nested types always have at least as many generic parameters as their enclosing type. このジェネリック パラメーターは、外側の型のジェネリック パラメーターに位置によって対応します。These correspond by position to the generic parameters in the enclosing type. ジェネリック型に新しいジェネリック パラメーターを含めることもできます。The generic type can also include new generic parameters.

外側の型のジェネリック型パラメーターと、その入れ子になった型の関係は、個別の言語構文によって非表示になっていることがあります。The relationship between the generic type parameters of a containing type and its nested types may be hidden by the syntax of individual languages. 次の例では、入れ子になった 2 つのクラス、Outer<T> および Inner1A が、ジェネリック型 Inner1B<U> に含まれます。In the following example, a generic type Outer<T> contains two nested classes, Inner1A and Inner1B<U>. 各クラスが ToString から継承した Object.ToString メソッドへの呼び出しは、入れ子になった各クラスに、その外側のクラスの型パラメーターが含まれていることを示しています。The calls to the ToString method, which each class inherits from Object.ToString, show that each nested class includes the type parameters of its containing class.

using System;

[assembly:CLSCompliant(true)]

public class Outer<T>
{
   T value;
   
   public Outer(T value)
   {
      this.value = value;
   }
   
   public class Inner1A : Outer<T>
   {
      public Inner1A(T value) : base(value)
      {  }
   }
   
   public class Inner1B<U> : Outer<T>
   {
      U value2;
      
      public Inner1B(T value1, U value2) : base(value1)
      {
         this.value2 = value2;
      }
   }
}

public class Example
{
   public static void Main()
   {
      var inst1 = new Outer<String>("This");
      Console.WriteLine(inst1);
      
      var inst2 = new Outer<String>.Inner1A("Another");
      Console.WriteLine(inst2);
      
      var inst3 = new Outer<String>.Inner1B<int>("That", 2);
      Console.WriteLine(inst3);
   }
}
// The example displays the following output:
//       Outer`1[System.String]
//       Outer`1+Inner1A[System.String]
//       Outer`1+Inner1B`1[System.String,System.Int32]
<Assembly:CLSCompliant(True)>

Public Class Outer(Of T)
   Dim value As T
   
   Public Sub New(value As T)
      Me.value = value
   End Sub
   
   Public Class Inner1A : Inherits Outer(Of T)
      Public Sub New(value As T)
         MyBase.New(value)
      End Sub
   End Class
   
   Public Class Inner1B(Of U) : Inherits Outer(Of T)
      Dim value2 As U
      
      Public Sub New(value1 As T, value2 As U)
         MyBase.New(value1)
         Me.value2 = value2
      End Sub
   End Class
End Class

Public Module Example
   Public Sub Main()
      Dim inst1 As New Outer(Of String)("This")
      Console.WriteLine(inst1)
      
      Dim inst2 As New Outer(Of String).Inner1A("Another")
      Console.WriteLine(inst2)
      
      Dim inst3 As New Outer(Of String).Inner1B(Of Integer)("That", 2)
      Console.WriteLine(inst3)
   End Sub
End Module
' The example displays the following output:
'       Outer`1[System.String]
'       Outer`1+Inner1A[System.String]
'       Outer`1+Inner1B`1[System.String,System.Int32]

ジェネリック型の名前は、フォーム name`n でエンコードされます。ここで、name は型の名前、` は文字リテラル、n は型で宣言されたパラメーターの数、入れ子になったジェネリック型の場合は、新しく導入された型パラメーターの数です。Generic type names are encoded in the form name`n, where name is the type name, ` is a character literal, and n is the number of parameters declared on the type, or, for nested generic types, the number of newly introduced type parameters. ジェネリック型の名前のエンコーディングは、主に、リフレクションを使用してライブラリ内の CLS 準拠のジェネリック型にアクセスする開発者が使用します。This encoding of generic type names is primarily of interest to developers who use reflection to access CLS-complaint generic types in a library.

制約がジェネリック型に適用される場合は、制約として使用されるすべての型も CLS に準拠している必要があります。If constraints are applied to a generic type, any types used as constraints must also be CLS-compliant. 次の例では、CLS に準拠していない BaseClass という名前のクラスと、型パラメーターが BaseCollection から派生しなければならない BaseClass という名前のジェネリック クラスを定義します。The following example defines a class named BaseClass that is not CLS-compliant and a generic class named BaseCollection whose type parameter must derive from BaseClass. ただし、BaseClass が CLS に準拠していないので、コンパイラによって警告が生成されます。But because BaseClass is not CLS-compliant, the compiler emits a warning.

using System;

[assembly:CLSCompliant(true)]

[CLSCompliant(false)] public class BaseClass
{}


public class BaseCollection<T> where T : BaseClass
{}
// Attempting to compile the example displays the following output:
//    warning CS3024: Constraint type 'BaseClass' is not CLS-compliant
<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> Public Class BaseClass
End Class


Public Class BaseCollection(Of T As BaseClass)
End Class
' Attempting to compile the example displays the following output:
'    warning BC40040: Generic parameter constraint type 'BaseClass' is not 
'    CLS-compliant.
'    
'    Public Class BaseCollection(Of T As BaseClass)
'                                        ~~~~~~~~~

ジェネリック型がジェネリック基本型から派生している場合、そのジェネリック型は、基本型に対する制約も必ず満たすように制約を再宣言する必要があります。If a generic type is derived from a generic base type, it must redeclare any constraints so that it can guarantee that constraints on the base type are also satisfied. 次の例では、任意の数値型を表すことができる Number<T> を定義します。The following example defines a Number<T> that can represent any numeric type. また、浮動小数点値を表す FloatingPoint<T> クラスも定義します。It also defines a FloatingPoint<T> class that represents a floating point value. ただし、ソース コードはコンパイルされません。Number<T> (T は値型) の制約は FloatingPoint<T> に適用されないからです。However, the source code fails to compile, because it does not apply the constraint on Number<T> (that T must be a value type) to FloatingPoint<T>.

using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct
{
   // use Double as the underlying type, since its range is a superset of
   // the ranges of all numeric types except BigInteger.
   protected double number;
      
   public Number(T value)
   {
      try {
         this.number = Convert.ToDouble(value);
      }  
      catch (OverflowException e) {
         throw new ArgumentException("value is too large.", e);
      }
      catch (InvalidCastException e) {
         throw new ArgumentException("The value parameter is not numeric.", e);
      }
   }

   public T Add(T value)
   {
      return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
   }

   public T Subtract(T value)
   {
      return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
   }
}
 
public class FloatingPoint<T> : Number<T> 
{
   public FloatingPoint(T number) : base(number) 
   {
      if (typeof(float) == number.GetType() ||
          typeof(double) == number.GetType() || 
          typeof(decimal) == number.GetType())
         this.number = Convert.ToDouble(number);
      else   
         throw new ArgumentException("The number parameter is not a floating-point number.");
   }       
}           
// The attempt to comple the example displays the following output:
//       error CS0453: The type 'T' must be a non-nullable value type in
//               order to use it as parameter 'T' in the generic type or method 'Number<T>'
<Assembly:CLSCompliant(True)>

Public Class Number(Of T As Structure)
   ' Use Double as the underlying type, since its range is a superset of
   ' the ranges of all numeric types except BigInteger.
   Protected number As Double
      
   Public Sub New(value As T)
      Try
         Me.number = Convert.ToDouble(value)
      Catch e As OverflowException
         Throw New ArgumentException("value is too large.", e)
      Catch e As InvalidCastException
         Throw New ArgumentException("The value parameter is not numeric.", e)
      End Try
   End Sub

   Public Function Add(value As T) As T
      Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
   End Function

   Public Function Subtract(value As T) As T
      Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
   End Function
End Class
 
Public Class FloatingPoint(Of T) : Inherits Number(Of T) 
   Public Sub New(number As T)
      MyBase.New(number) 
      If TypeOf number Is Single Or
               TypeOf number Is Double Or
               TypeOf number Is Decimal Then 
         Me.number = Convert.ToDouble(number)
      Else   
         throw new ArgumentException("The number parameter is not a floating-point number.")
      End If   
   End Sub       
End Class           
' The attempt to comple the example displays the following output:
'    error BC32105: Type argument 'T' does not satisfy the 'Structure'
'    constraint for type parameter 'T'.
'    
'    Public Class FloatingPoint(Of T) : Inherits Number(Of T)
'                                                          ~

制約が FloatingPoint<T> クラスに追加されると、コンパイルが正常に行われます。The example compiles successfully if the constraint is added to the FloatingPoint<T> class.

using System;

[assembly:CLSCompliant(true)]


public class Number<T> where T : struct
{
   // use Double as the underlying type, since its range is a superset of
   // the ranges of all numeric types except BigInteger.
   protected double number;
      
   public Number(T value)
   {
      try {
         this.number = Convert.ToDouble(value);
      }  
      catch (OverflowException e) {
         throw new ArgumentException("value is too large.", e);
      }
      catch (InvalidCastException e) {
         throw new ArgumentException("The value parameter is not numeric.", e);
      }
   }

   public T Add(T value)
   {
      return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
   }

   public T Subtract(T value)
   {
      return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
   }
}
 
public class FloatingPoint<T> : Number<T> where T : struct 
{
   public FloatingPoint(T number) : base(number) 
   {
      if (typeof(float) == number.GetType() ||
          typeof(double) == number.GetType() || 
          typeof(decimal) == number.GetType())
         this.number = Convert.ToDouble(number);
      else   
         throw new ArgumentException("The number parameter is not a floating-point number.");
   }       
}           
<Assembly:CLSCompliant(True)>

Public Class Number(Of T As Structure)
   ' Use Double as the underlying type, since its range is a superset of
   ' the ranges of all numeric types except BigInteger.
   Protected number As Double
      
   Public Sub New(value As T)
      Try
         Me.number = Convert.ToDouble(value)
      Catch e As OverflowException
         Throw New ArgumentException("value is too large.", e)
      Catch e As InvalidCastException
         Throw New ArgumentException("The value parameter is not numeric.", e)
      End Try
   End Sub

   Public Function Add(value As T) As T
      Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
   End Function

   Public Function Subtract(value As T) As T
      Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
   End Function
End Class
 
Public Class FloatingPoint(Of T As Structure) : Inherits Number(Of T) 
   Public Sub New(number As T)
      MyBase.New(number) 
      If TypeOf number Is Single Or
               TypeOf number Is Double Or
               TypeOf number Is Decimal Then 
         Me.number = Convert.ToDouble(number)
      Else   
         throw new ArgumentException("The number parameter is not a floating-point number.")
      End If   
   End Sub       
End Class           

共通言語仕様では、入れ子になった型とプロテクト メンバーに対して従来のインスタンス化ごとのモデルが適用されます。The Common Language Specification imposes a conservative per-instantiation model for nested types and protected members. オープン ジェネリック型では、フィールドまたはメンバーのシグネチャに、入れ子になったプロテクト ジェネリック型の特定のインスタンス化が含まれている場合、これらのフィールドやメンバーは公開できません。Open generic types cannot expose fields or members with signatures that contain a specific instantiation of a nested, protected generic type. ジェネリックの基底クラスやインターフェイスについて特定のインスタンス化を拡張する非ジェネリック型では、フィールドまたはメンバーのシグネチャに、入れ子になったプロテクト ジェネリック型の別のインスタンス化が含まれている場合、これらのフィールドやメンバーは公開できません。Non-generic types that extend a specific instantiation of a generic base class or interface cannot expose fields or members with signatures that contain a different instantiation of a nested, protected generic type.

次の例では、ジェネリック型 C1<T> (Visual Basic の場合は C1(Of T))、およびプロテクト クラス C1<T>.N (Visual Basic の場合は C1(Of T).N) を定義します。The following example defines a generic type, C1<T> (or C1(Of T) in Visual Basic), and a protected class, C1<T>.N (or C1(Of T).N in Visual Basic). C1<T> には、2 つのメソッド M1M2 があります。C1<T> has two methods, M1 and M2. ただし、M1 は、C1<int>.N (C1(Of Integer).N) オブジェクトを C1<T> (または C1(Of T)) から返そうとするので、CLS に準拠していません。However, M1 is not CLS-compliant because it tries to return a C1<int>.N (or C1(Of Integer).N) object from C1<T> (or C1(Of T)). 2 番目の C2 クラスは、C1<long> (C1(Of Long)) から派生しています。A second class, C2, is derived from C1<long> (or C1(Of Long)). これには、M3M4 の 2 つのメソッドがあります。It has two methods, M3 and M4. M3 は、C1<int>.N (C1(Of Integer).N) オブジェクトを C1<long> のサブクラスから返そうとするので、CLS に準拠していません。M3 is not CLS-compliant because it tries to return a C1<int>.N (or C1(Of Integer).N) object from a subclass of C1<long>. 言語コンパイラはさらに制限されている可能性があります。Note that language compilers can be even more restrictive. この例では、Visual Basic で M4 をコンパイルしようとするとエラーが表示されます。In this example, Visual Basic displays an error when it tries to compile M4.

using System;

[assembly:CLSCompliant(true)]

public class C1<T> 
{
   protected class N { }

   protected void M1(C1<int>.N n) { } // Not CLS-compliant - C1<int>.N not
                                      // accessible from within C1<T> in all
                                      // languages
   protected void M2(C1<T>.N n) { }   // CLS-compliant – C1<T>.N accessible
                                      // inside C1<T>
}

public class C2 : C1<long> 
{
   protected void M3(C1<int>.N n) { }  // Not CLS-compliant – C1<int>.N is not
                                       // accessible in C2 (extends C1<long>)

   protected void M4(C1<long>.N n) { } // CLS-compliant, C1<long>.N is
                                       // accessible in C2 (extends C1<long>)
}
// Attempting to compile the example displays output like the following:
//       Generics4.cs(9,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
//       Generics4.cs(18,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
<Assembly:CLSCompliant(True)>

Public Class C1(Of T) 
   Protected Class N
   End Class

   Protected Sub M1(n As C1(Of Integer).N)   ' Not CLS-compliant - C1<int>.N not
                                             ' accessible from within C1(Of T) in all
   End Sub                                   ' languages


   Protected Sub M2(n As C1(Of T).N)     ' CLS-compliant – C1(Of T).N accessible
   End Sub                               ' inside C1(Of T)
End Class

Public Class C2 : Inherits C1(Of Long) 
   Protected Sub M3(n As C1(Of Integer).N)   ' Not CLS-compliant – C1(Of Integer).N is not
   End Sub                                   ' accessible in C2 (extends C1(Of Long))

   Protected Sub M4(n As C1(Of Long).N)   
   End Sub                                
End Class
' Attempting to compile the example displays output like the following:
'    error BC30508: 'n' cannot expose type 'C1(Of Integer).N' in namespace 
'    '<Default>' through class 'C1'.
'    
'       Protected Sub M1(n As C1(Of Integer).N)   ' Not CLS-compliant - C1<int>.N not
'                             ~~~~~~~~~~~~~~~~
'    error BC30389: 'C1(Of T).N' is not accessible in this context because 
'    it is 'Protected'.
'    
'       Protected Sub M3(n As C1(Of Integer).N)   ' Not CLS-compliant - C1(Of Integer).N is not
'    
'                             ~~~~~~~~~~~~~~~~
'    
'    error BC30389: 'C1(Of T).N' is not accessible in this context because it is 'Protected'.
'    
'       Protected Sub M4(n As C1(Of Long).N)  
'                             ~~~~~~~~~~~~~

コンストラクターConstructors

CLS 準拠のクラスと構造体のコンストラクターは、次の規則に従う必要があります。Constructors in CLS-compliant classes and structures must follow these rules:

  • 派生クラスのコンストラクターは、継承されたインスタンス データにアクセスする前に、基底クラスのインスタンス コンストラクターを呼び出す必要があります。A constructor of a derived class must call the instance constructor of its base class before it accesses inherited instance data. これは、基底クラスのコンストラクターは派生クラスには継承されないからです。This requirement is due to the fact that base class constructors are not inherited by their derived classes. この規則は、直接継承をサポートしない構造体に適用されません。This rule does not apply to structures, which do not support direct inheritance.

    次の例に示すように、コンパイラは、通常、CLS 準拠とは別にこの規則を適用します。Typically, compilers enforce this rule independently of CLS compliance, as the following example shows. これにより、Doctor クラスから派生した Person クラスが作成されますが、Doctor クラスでは、継承されたインスタンス フィールドを初期化するための Person クラス コンストラクターは呼び出されません。It creates a Doctor class that is derived from a Person class, but the Doctor class fails to call the Person class constructor to initialize inherited instance fields.

    using System;
    
    [assembly: CLSCompliant(true)]
    
    public class Person
    {
       private string fName, lName, _id;
       
       public Person(string firstName, string lastName, string id)
       {
          if (String.IsNullOrEmpty(firstName + lastName))
             throw new ArgumentNullException("Either a first name or a last name must be provided.");    
          
          fName = firstName;
          lName = lastName;
          _id = id;
       }
       
       public string FirstName 
       {
          get { return fName; }
       }
    
       public string LastName 
       {
          get { return lName; }
       }
       
       public string Id 
       {
          get { return _id; }
       }
    
       public override string ToString()
       {
          return String.Format("{0}{1}{2}", fName, 
                               String.IsNullOrEmpty(fName) ?  "" : " ",
                               lName);
       }
    }
    
    public class Doctor : Person
    {
       public Doctor(string firstName, string lastName, string id)
       {
       }
    
       public override string ToString()
       {
          return "Dr. " + base.ToString();
       }
    }
    // Attempting to compile the example displays output like the following:
    //    ctor1.cs(45,11): error CS1729: 'Person' does not contain a constructor that takes 0
    //            arguments
    //    ctor1.cs(10,11): (Location of symbol related to previous error)
    
    <Assembly: CLSCompliant(True)> 
    
    Public Class Person
       Private fName, lName, _id As String
       
       Public Sub New(firstName As String, lastName As String, id As String)
          If String.IsNullOrEmpty(firstName + lastName) Then
             Throw New ArgumentNullException("Either a first name or a last name must be provided.")    
          End If
          
          fName = firstName
          lName = lastName
          _id = id
       End Sub
       
       Public ReadOnly Property FirstName As String
          Get
             Return fName
          End Get
       End Property
    
       Public ReadOnly Property LastName As String
          Get
             Return lName
          End Get
       End Property
       
       Public ReadOnly Property Id As String
          Get
             Return _id
          End Get
       End Property
    
       Public Overrides Function ToString() As String
          Return String.Format("{0}{1}{2}", fName, 
                               If(String.IsNullOrEmpty(fName), "", " "),
                               lName)
       End Function
    End Class
    
    Public Class Doctor : Inherits Person
       Public Sub New(firstName As String, lastName As String, id As String)
       End Sub
    
       Public Overrides Function ToString() As String
          Return "Dr. " + MyBase.ToString()
       End Function
    End Class
    ' Attempting to compile the example displays output like the following:
    '    Ctor1.vb(46) : error BC30148: First statement of this 'Sub New' must be a call 
    '    to 'MyBase.New' or 'MyClass.New' because base class 'Person' of 'Doctor' does 
    '    not have an accessible 'Sub New' that can be called with no arguments.
    '    
    '       Public Sub New()
    '                  ~~~
    
  • オブジェクト作成以外の目的で、オブジェクト コンストラクターを呼び出すことはできません。An object constructor cannot be called except to create an object. また、オブジェクトを 2 度初期化することもできません。In addition, an object cannot be initialized twice. たとえば、これは Object.MemberwiseClone メソッド、および BinaryFormatter.Deserialize などの逆シリアル化メソッドでは、コンストラクターを呼び出してはいけないことを意味します。For example, this means that Object.MemberwiseClone and deserialization methods such as BinaryFormatter.Deserialize must not call constructors.

プロパティProperties

CLS 準拠型のプロパティは、次の規則に従う必要があります。Properties in CLS-compliant types must follow these rules:

  • プロパティには setter、getter、またはこの両方が必ず必要です。A property must have a setter, a getter, or both. アセンブリでは、これらは特殊なメソッドとして実装されます。つまり、個別のメソッドとして (getter は get_propertyname、setter は set_propertyname という名前で) 表示され、アセンブリのメタデータでは SpecialName としてマークされます。In an assembly, these are implemented as special methods, which means that they will appear as separate methods (the getter is named get_propertyname and the setter is set_propertyname) marked as SpecialName in the assembly's metadata. C# コンパイラおよび Visual Basic コンパイラでは、この規則が自動的に適用されます。CLSCompliantAttribute 属性を適用する必要はありません。The C# and Visual Basic compilers enforce this rule automatically without the need to apply the CLSCompliantAttribute attribute.

  • プロパティの型は、プロパティ get アクセス操作子、および set アクセス操作子の最後の引数の戻り値の型です。A property's type is the return type of the property getter and the last argument of the setter. これらの型は CLS に準拠している必要があり、引数を参照によってプロパティに割り当てることはできません (つまり、マネージド ポインターにできません)。These types must be CLS compliant, and arguments cannot be assigned to the property by reference (that is, they cannot be managed pointers).

  • プロパティに get アクセス操作子と set アクセス操作子の両方がある場合は、両方が仮想、両方が静的、または両方がインスタンスである必要があります。If a property has both a getter and a setter, they must both be virtual, both static, or both instance. C# コンパイラおよび Visual Basic コンパイラでは、この規則がプロパティ定義構文によって自動的に適用されます。The C# and Visual Basic compilers automatically enforce this rule through their property definition syntax.

イベントEvents

イベントは、名前と型によって定義されます。An event is defined by its name and its type. イベントの型は、イベントの表示に使用されるデリゲートです。The event type is a delegate that is used to indicate the event. たとえば、AppDomain.AssemblyResolve イベントは ResolveEventHandler 型です。For example, the AppDomain.AssemblyResolve event is of type ResolveEventHandler. イベント自体のほか、イベント名に基づく名前の 3 つのメソッドがイベントの実装を提供し、アセンブリのメタデータで SpecialName としてマークされています。In addition to the event itself, three methods with names based on the event name provide the event's implementation and are marked as SpecialName in the assembly's metadata:

  • イベント ハンドラーを追加するメソッド (add_EventName)。A method for adding an event handler, named add_EventName. たとえば、AppDomain.AssemblyResolve イベントのイベント サブスクリプション メソッドの名前は add_AssemblyResolve です。For example, the event subscription method for the AppDomain.AssemblyResolve event is named add_AssemblyResolve.

  • イベント ハンドラーを削除するメソッド (remove_EventName)。A method for removing an event handler, named remove_EventName. たとえば、AppDomain.AssemblyResolve イベントの削除メソッドの名前は remove_AssemblyResolve です。For example, the removal method for the AppDomain.AssemblyResolve event is named remove_AssemblyResolve.

  • イベントが発生したことを示すメソッド (raise_EventName)。A method for indicating that the event has occurred, named raise_EventName.

注意

イベントに関する共通言語仕様の規則は、ほとんどが言語コンパイラによって実装され、コンポーネント開発者が意識せずに使用できます。Most of the Common Language Specification's rules regarding events are implemented by language compilers and are transparent to component developers.

イベントの追加、削除、発生の各メソッドには同じアクセシビリティが必要です。The methods for adding, removing, and raising the event must have the same accessibility. また、すべてが、静的メソッド、インスタンス メソッド、仮想メソッドのいずれかでなければなりません。They must also all be static, instance, or virtual. イベントを追加および削除するメソッドには、イベント デリゲート型の型を持つパラメーターが 1 つあります。The methods for adding and removing an event have one parameter whose type is the event delegate type. 追加メソッドおよび削除メソッドは両方とも存在するか、両方存在しないかのいずれかでなければなりません。The add and remove methods must both be present or both be absent.

次の例では、2 つのポイントの気温の差がしきい値と等しいか、それを超えた場合に Temperature イベントを発生させる、TemperatureChanged という名前の CLS 準拠クラスを定義します。The following example defines a CLS-compliant class named Temperature that raises a TemperatureChanged event if the change in temperature between two readings equals or exceeds a threshold value. Temperature クラスは、イベント ハンドラーを選択的に実行できるように、raise_TemperatureChanged メソッドを明示的に定義します。The Temperature class explicitly defines a raise_TemperatureChanged method so that it can selectively execute event handlers.

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

[assembly: CLSCompliant(true)]

public class TemperatureChangedEventArgs : EventArgs
{
   private Decimal originalTemp;
   private Decimal newTemp; 
   private DateTimeOffset when;
   
   public TemperatureChangedEventArgs(Decimal original, Decimal @new, DateTimeOffset time)
   {
      originalTemp = original;
      newTemp = @new;
      when = time;
   }   
   
   public Decimal OldTemperature
   {
      get { return originalTemp; }
   } 
   
   public Decimal CurrentTemperature
   {
      get { return newTemp; }
   } 
   
   public DateTimeOffset Time
   {
      get { return when; }
   }
}

public delegate void TemperatureChanged(Object sender, TemperatureChangedEventArgs e);

public class Temperature
{
   private struct TemperatureInfo
   {
      public Decimal Temperature;
      public DateTimeOffset Recorded;
   }
   
   public event TemperatureChanged TemperatureChanged;

   private Decimal previous;
   private Decimal current;
   private Decimal tolerance;
   private List<TemperatureInfo> tis = new List<TemperatureInfo>();
      
   public Temperature(Decimal temperature, Decimal tolerance)
   {
      current = temperature;
      TemperatureInfo ti = new TemperatureInfo();
      ti.Temperature = temperature;
      tis.Add(ti);
      ti.Recorded = DateTimeOffset.UtcNow;
      this.tolerance = tolerance;
   }
 
   public Decimal CurrentTemperature
   {
      get { return current; }
      set {
         TemperatureInfo ti = new TemperatureInfo();
         ti.Temperature = value;
         ti.Recorded = DateTimeOffset.UtcNow;
         previous = current;
         current = value;
         if (Math.Abs(current - previous) >= tolerance) 
            raise_TemperatureChanged(new TemperatureChangedEventArgs(previous, current, ti.Recorded));
      }
   }
   
   public void raise_TemperatureChanged(TemperatureChangedEventArgs eventArgs)
   {
      if (TemperatureChanged == null)
         return; 

      foreach (TemperatureChanged d in TemperatureChanged.GetInvocationList()) {
         if (d.Method.Name.Contains("Duplicate"))
            Console.WriteLine("Duplicate event handler; event handler not executed.");
         else
            d.Invoke(this, eventArgs);
      }
   }
}

public class Example
{
   public Temperature temp;
   
   public static void Main()
   {
      Example ex = new Example();
   }

   public Example()
   {
      temp = new Temperature(65, 3);
      temp.TemperatureChanged += this.TemperatureNotification;
      RecordTemperatures();
      Example ex = new Example(temp);
      ex.RecordTemperatures();
   }
      
   public Example(Temperature t)
   {
      temp = t;
      RecordTemperatures();
   }
   
   public void RecordTemperatures()
   {
      temp.TemperatureChanged += this.DuplicateTemperatureNotification;
      temp.CurrentTemperature = 66;
      temp.CurrentTemperature = 63;
   }
   
   internal void TemperatureNotification(Object sender, TemperatureChangedEventArgs e) 
   {
      Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature, e.CurrentTemperature);   
   }
   
   public void DuplicateTemperatureNotification(Object sender, TemperatureChangedEventArgs e)
   { 
      Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature, e.CurrentTemperature);   
   }
}
Imports System.Collections
Imports System.Collections.Generic

<Assembly: CLSCompliant(True)>

Public Class TemperatureChangedEventArgs   : Inherits EventArgs
   Private originalTemp As Decimal
   Private newTemp As Decimal 
   Private [when] As DateTimeOffset
   
   Public Sub New(original As Decimal, [new] As Decimal, [time] As DateTimeOffset)
      originalTemp = original
      newTemp = [new]
      [when] = [time]
   End Sub   
   
   Public ReadOnly Property OldTemperature As Decimal
      Get
         Return originalTemp
      End Get
   End Property 
   
   Public ReadOnly Property CurrentTemperature As Decimal
      Get
         Return newTemp
      End Get
   End Property 
   
   Public ReadOnly Property [Time] As DateTimeOffset
      Get
         Return [when]
      End Get
   End Property
End Class

Public Delegate Sub TemperatureChanged(sender As Object, e As TemperatureChangedEventArgs)

Public Class Temperature
   Private Structure TemperatureInfo
      Dim Temperature As Decimal
      Dim Recorded As DateTimeOffset
   End Structure
   
   Public Event TemperatureChanged As TemperatureChanged

   Private previous As Decimal
   Private current As Decimal
   Private tolerance As Decimal
   Private tis As New List(Of TemperatureInfo)
      
   Public Sub New(temperature As Decimal, tolerance As Decimal)
      current = temperature
      Dim ti As New TemperatureInfo()
      ti.Temperature = temperature
      ti.Recorded = DateTimeOffset.UtcNow
      tis.Add(ti)
      Me.tolerance = tolerance
   End Sub

   Public Property CurrentTemperature As Decimal
      Get
         Return current
      End Get
      Set
         Dim ti As New TemperatureInfo
         ti.Temperature = value
         ti.Recorded = DateTimeOffset.UtcNow
         previous = current
         current = value
         If Math.Abs(current - previous) >= tolerance Then
            raise_TemperatureChanged(New TemperatureChangedEventArgs(previous, current, ti.Recorded))
         End If
      End Set
   End Property
   
   Public Sub raise_TemperatureChanged(eventArgs As TemperatureChangedEventArgs)
      If TemperatureChangedEvent Is Nothing Then Exit Sub

      Dim ListenerList() As System.Delegate = TemperatureChangedEvent.GetInvocationList()
      For Each d As TemperatureChanged In TemperatureChangedEvent.GetInvocationList()
         If d.Method.Name.Contains("Duplicate") Then
            Console.WriteLine("Duplicate event handler; event handler not executed.")
         Else
            d.Invoke(Me, eventArgs)
         End If
      Next
   End Sub
End Class

Public Class Example
   Public WithEvents temp As Temperature
   
   Public Shared Sub Main()
      Dim ex As New Example()
   End Sub

   Public Sub New()
      temp = New Temperature(65, 3)
      RecordTemperatures()
      Dim ex As New Example(temp)
      ex.RecordTemperatures()
   End Sub
      
   Public Sub New(t As Temperature)
      temp = t
      RecordTemperatures()
   End Sub
   
   Public Sub RecordTemperatures()
      temp.CurrentTemperature = 66
      temp.CurrentTemperature = 63
   
   End Sub
   
   Friend Shared Sub TemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _
          Handles temp.TemperatureChanged
      Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature, e.CurrentTemperature)   
   End Sub
   
   Friend Shared Sub DuplicateTemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _
          Handles temp.TemperatureChanged
      Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature, e.CurrentTemperature)   
   End Sub
End Class

OverloadsOverloads

共通言語仕様では、次の要件がオーバーロード メンバーに適用されます。The Common Language Specification imposes the following requirements on overloaded members:

  • メンバーは、パラメーターの数および型に基づいてオーバーロードできます。Members can be overloaded based on the number of parameters and the type of any parameter. オーバーロードを区別するときに、呼び出し規約、戻り値の型、メソッドまたはそのパラメーターに適用されているカスタム修飾子、およびパラメーターが値渡しか参照渡しかは考慮されません。Calling convention, return type, custom modifiers applied to the method or its parameter, and whether parameters are passed by value or by reference are not considered when differentiating between overloads. 例については、「名前付け規則」で、名前がスコープ内で一意であることを要求する要件のコードを参照してください。For an example, see the code for the requirement that names must be unique within a scope in the Naming conventions section.

  • プロパティおよびメソッドのみオーバーロードできる。Only properties and methods can be overloaded. フィールドとイベントはオーバーロードできません。Fields and events cannot be overloaded.

  • ジェネリック メソッドは、ジェネリック パラメーターの数に基づいてオーバーロードできます。Generic methods can be overloaded based on the number of their generic parameters.

注意

op_Explicit 演算子および op_Implicit 演算子にはこの規則が適用されず、戻り値は、オーバーロード解決のためのメソッド シグネチャの一部として見なされません。The op_Explicit and op_Implicit operators are exceptions to the rule that return value is not considered part of a method signature for overload resolution. この 2 つの演算子は、そのパラメーターと戻り値の両方に基づいてオーバーロードできます。These two operators can be overloaded based on both their parameters and their return value.

例外Exceptions

例外オブジェクトは System.Exception、または System.Exception の別の派生型から派生する必要があります。Exception objects must derive from System.Exception or from another type derived from System.Exception. 次の例は、ErrorClass というカスタム クラスを例外処理に使用したときに発生するコンパイラ エラーを示しています。The following example illustrates the compiler error that results when a custom class named ErrorClass is used for exception handling.

using System;

[assembly: CLSCompliant(true)]

public class ErrorClass
{ 
   string msg;
   
   public ErrorClass(string errorMessage)
   {
      msg = errorMessage;
   }
   
   public string Message
   {
      get { return msg; }
   }
}

public static class StringUtilities
{
   public static string[] SplitString(this string value, int index)
   {
      if (index < 0 | index > value.Length) {
         ErrorClass badIndex = new ErrorClass("The index is not within the string.");
         throw badIndex;
      }
      string[] retVal = { value.Substring(0, index - 1), 
                          value.Substring(index) };
      return retVal;
   }
}
// Compilation produces a compiler error like the following:
//    Exceptions1.cs(26,16): error CS0155: The type caught or thrown must be derived from
//            System.Exception
Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>
 
Public Class ErrorClass 
   Dim msg As String
   
   Public Sub New(errorMessage As String)
      msg = errorMessage
   End Sub
   
   Public ReadOnly Property Message As String
      Get
         Return msg
      End Get   
   End Property
End Class

Public Module StringUtilities
   <Extension()> Public Function SplitString(value As String, index As Integer) As String()
      If index < 0 Or index > value.Length Then
         Dim BadIndex As New ErrorClass("The index is not within the string.")
         Throw BadIndex
      End If
      Dim retVal() As String = { value.Substring(0, index - 1), 
                                 value.Substring(index) }
      Return retVal
   End Function
End Module
' Compilation produces a compiler error like the following:
'    Exceptions1.vb(27) : error BC30665: 'Throw' operand must derive from 'System.Exception'.
'    
'             Throw BadIndex
'             ~~~~~~~~~~~~~~

このエラーを修正するには、ErrorClass から継承するように System.Exception クラスを指定する必要があります。To correct this error, the ErrorClass class must inherit from System.Exception. また、Message プロパティはオーバーライドする必要があります。In addition, the Message property must be overridden. 次の例では、このエラーを修正して CLS 準拠の ErrorClass クラスを定義します。The following example corrects these errors to define an ErrorClass class that is CLS-compliant.

using System;

[assembly: CLSCompliant(true)]

public class ErrorClass : Exception
{ 
   string msg;
   
   public ErrorClass(string errorMessage)
   {
      msg = errorMessage;
   }
   
   public override string Message
   {
      get { return msg; }
   }
}

public static class StringUtilities
{
   public static string[] SplitString(this string value, int index)
   {
      if (index < 0 | index > value.Length) {
         ErrorClass badIndex = new ErrorClass("The index is not within the string.");
         throw badIndex;
      }
      string[] retVal = { value.Substring(0, index - 1), 
                          value.Substring(index) };
      return retVal;
   }
}
Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>
 
Public Class ErrorClass : Inherits Exception
   Dim msg As String
   
   Public Sub New(errorMessage As String)
      msg = errorMessage
   End Sub
   
   Public Overrides ReadOnly Property Message As String
      Get
         Return msg
      End Get   
   End Property
End Class

Public Module StringUtilities
   <Extension()> Public Function SplitString(value As String, index As Integer) As String()
      If index < 0 Or index > value.Length Then
         Dim BadIndex As New ErrorClass("The index is not within the string.")
         Throw BadIndex
      End If
      Dim retVal() As String = { value.Substring(0, index - 1), 
                                 value.Substring(index) }
      Return retVal
   End Function
End Module

属性Attributes

.NET Framework アセンブリでは、カスタム属性に拡張可能機構が用意されており、そのカスタム属性を格納し、アセンブリ、型、メンバー、メソッド パラメーターなどのプログラミング オブジェクトに関するメタデータを取得します。In.NET Framework assemblies, custom attributes provide an extensible mechanism for storing custom attributes and retrieving metadata about programming objects, such as assemblies, types, members, and method parameters. カスタム属性は System.Attribute、または System.Attribute の派生型から派生する必要があります。Custom attributes must derive from System.Attribute or from a type derived from System.Attribute.

規則に違反する例を次に示します。The following example violates this rule. この例では、NumericAttribute から派生していない System.Attribute クラスを定義します。It defines a NumericAttribute class that does not derive from System.Attribute. コンパイラ エラーは、CLS 非準拠の属性が適用されている場合にのみ発生します。クラスが定義されているときではありません。Note that a compiler error results only when the non-CLS-compliant attribute is applied, not when the class is defined.

using System;

[assembly: CLSCompliant(true)]

[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct)] 
public class NumericAttribute
{
   private bool _isNumeric;
   
   public NumericAttribute(bool isNumeric)
   {
      _isNumeric = isNumeric;
   }
   
   public bool IsNumeric 
   {
      get { return _isNumeric; }
   }
}

[Numeric(true)] public struct UDouble
{
   double Value;
}
// Compilation produces a compiler error like the following:
//    Attribute1.cs(22,2): error CS0616: 'NumericAttribute' is not an attribute class
//    Attribute1.cs(7,14): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

<AttributeUsageAttribute(AttributeTargets.Class Or AttributeTargets.Struct)> _
Public Class NumericAttribute
   Private _isNumeric As Boolean
   
   Public Sub New(isNumeric As Boolean)
      _isNumeric = isNumeric
   End Sub
   
   Public ReadOnly Property IsNumeric As Boolean
      Get
         Return _isNumeric
      End Get
   End Property
End Class

<Numeric(True)> Public Structure UDouble
   Dim Value As Double
End Structure
' Compilation produces a compiler error like the following:
'    error BC31504: 'NumericAttribute' cannot be used as an attribute because it 
'    does not inherit from 'System.Attribute'.
'    
'    <Numeric(True)> Public Structure UDouble
'     ~~~~~~~~~~~~~

CLS 準拠の属性のコンストラクターまたはプロパティは、次の型のみを公開できます。The constructor or the properties of a CLS-compliant attribute can expose only the following types:

次の例では、DescriptionAttribute から派生する Attribute クラスを定義します。The following example defines a DescriptionAttribute class that derives from Attribute. クラス コンストラクターには型 Descriptor のパラメーターがあるので、クラスは CLS に準拠していません。The class constructor has a parameter of type Descriptor, so the class is not CLS-compliant. C# コンパイラでは警告が出力されますが、コンパイルは正常に行われます。一方、Visual Basic コンパイラでは警告もエラーも出力されません。Note that the C# compiler emits a warning but compiles successfully, whereas the Visual Basic compiler emits neither a warning nor an error.

using System;

[assembly:CLSCompliantAttribute(true)]

public enum DescriptorType { type, member };

public class Descriptor
{
   public DescriptorType Type;
   public String Description; 
}

[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
   private Descriptor desc;
   
   public DescriptionAttribute(Descriptor d)
   {
      desc = d; 
   }
   
   public Descriptor Descriptor
   { get { return desc; } } 
}
// Attempting to compile the example displays output like the following:
//       warning CS3015: 'DescriptionAttribute' has no accessible
//               constructors which use only CLS-compliant types
<Assembly:CLSCompliantAttribute(True)>

Public Enum DescriptorType As Integer
   Type = 0
   Member = 1
End Enum

Public Class Descriptor
   Public Type As DescriptorType 
   Public Description As String 
End Class

<AttributeUsage(AttributeTargets.All)> _
Public Class DescriptionAttribute : Inherits Attribute
   Private desc As Descriptor
   
   Public Sub New(d As Descriptor)
      desc = d 
   End Sub
   
   Public ReadOnly Property Descriptor As Descriptor
      Get 
         Return desc
      End Get    
   End Property
End Class

CLSCompliantAttribute 属性The CLSCompliantAttribute attribute

CLSCompliantAttribute 属性は、プログラム要素が共通言語仕様でコンパイルされているかどうかを示すために使用されます。The CLSCompliantAttribute attribute is used to indicate whether a program element complies with the Common Language Specification. CLSCompliantAttribute.CLSCompliantAttribute(Boolean) コンストラクターには、プログラム要素が CLS に準拠しているかどうかを示す 1 つの必須パラメーター、isCompliant が含まれます。The CLSCompliantAttribute.CLSCompliantAttribute(Boolean) constructor includes a single required parameter, isCompliant, that indicates whether the program element is CLS-compliant.

コンパイル時に、CLS 準拠が前提とされる非準拠要素が検出され、警告が出力されます。At compile time, the compiler detects non-compliant elements that are presumed to be CLS-compliant and emits a warning. 非準拠として明示的に宣言された型またはメンバーに対しては、警告は出力されません。The compiler does not emit warnings for types or members that are explicitly declared to be non-compliant.

コンポーネント開発者は、次の 2 とおりの目的で CLSCompliantAttribute 属性を使用できます。Component developers can use the CLSCompliantAttribute attribute in two ways:

  • コンポーネントによって公開されたパブリック インターフェイスの CLS 準拠部分と CLS 非準拠部分を定義する。To define the parts of the public interface exposed by a component that are CLS-compliant and the parts that are not CLS-compliant. この属性を使用して特定のプログラム要素を CLS 準拠としてマークすると、.NET Framework を対象とするすべてのツールおよび言語から、これらの要素に必ずアクセスできるようになります。When the attribute is used to mark particular program elements as CLS-compliant, its use guarantees that those elements are accessible from all languages and tools that target the .NET Framework.

  • コンポーネント ライブラリのパブリック インターフェイスが CLS に準拠するプログラム要素のみを公開するように保証する。To ensure that the component library's public interface exposes only program elements that are CLS-compliant. 要素が CLS 非準拠の場合は、通常、警告が表示されます。If elements are not CLS-compliant, compilers will generally issue a warning.

警告

言語コンパイラでは、CLSCompliantAttribute 属性が使用されているかどうかに関係なく、CLS 準拠の規則が適用される場合があります。In some cases, language compilers enforce CLS-compliant rules regardless of whether the CLSCompliantAttribute attribute is used. たとえば、インターフェイスの静的メンバーを定義すると CLS の規則に違反します。For example, defining a static member in an interface violates a CLS rule. この点に関して、インターフェイスで static メンバー (C# の場合) または Shared メンバー (Visual Basic の場合) を定義すると、C# と Visual Basic の両方のコンパイラでエラー メッセージが表示され、アプリはコンパイルされません。In this regard, if you define a static (in C#) or Shared (in Visual Basic) member in an interface, both the C# and Visual Basic compilers display an error message and fail to compile the app.

CLSCompliantAttribute 属性は、値 AttributeUsageAttribute が指定された AttributeTargets.All 属性でマークされます。The CLSCompliantAttribute attribute is marked with an AttributeUsageAttribute attribute that has a value of AttributeTargets.All. この値を使用すると、CLSCompliantAttribute 属性を、アセンブリ、モジュール、型 (クラス、構造体、列挙体、インターフェイス、およびデリゲート)、型パラメーター (コンストラクター、メソッド、プロパティ、フィールド、およびイベント)、パラメーター、ジェネリック パラメーター、戻り値など、すべてのプログラム要素に適用できます。This value allows you to apply the CLSCompliantAttribute attribute to any program element, including assemblies, modules, types (classes, structures, enumerations, interfaces, and delegates), type members (constructors, methods, properties, fields, and events), parameters, generic parameters, and return values. ただし、実際は、アセンブリ、型、および型メンバーだけに属性を適用することをお勧めします。However, in practice, you should apply the attribute only to assemblies, types, and type members. そうしないと、属性は、コンパイラによってライブラリのパブリック インターフェイスで非準拠パラメーター、ジェネリック パラメーター、または戻り値が検出されたときに必ず無視され、コンパイラ警告が引き続き生成されます。Otherwise, compilers ignore the attribute and continue to generate compiler warnings whenever they encounter a non-compliant parameter, generic parameter, or return value in your library's public interface.

CLSCompliantAttribute 属性の値は、内包型プログラム要素によって継承されます。The value of the CLSCompliantAttribute attribute is inherited by contained program elements. たとえば、アセンブリが CLS 準拠としてマークされている場合は、その型も CLS に準拠します。For example, if an assembly is marked as CLS-compliant, its types are also CLS-compliant. 型が CLS 準拠としてマークされている場合は、その入れ子になった型とメンバーも CLS に準拠します。If a type is marked as CLS-compliant, its nested types and members are also CLS-compliant.

継承された準拠状況を明示的にオーバーライドするには、CLSCompliantAttribute 属性を、格納されているプログラム要素に適用します。You can explicitly override the inherited compliance by applying the CLSCompliantAttribute attribute to a contained program element. たとえば、CLSCompliantAttribute 値が isCompliant に指定された false 属性を使用すると、準拠アセンブリで非準拠型を定義できます。また、isCompliant 値が true に指定された属性を使用すると、非準拠アセンブリで準拠型を定義できます。For example, you can use the CLSCompliantAttribute attribute with an isCompliant value of false to define a non-compliant type in a compliant assembly, and you can use the attribute with an isCompliant value of true to define a compliant type in a non-compliant assembly. 準拠型で非準拠メンバーを定義することもできます。You can also define non-compliant members in a compliant type. ただし、非準拠型は準拠メンバーを持つことができないので、isCompliant 値が true に指定された属性では非準拠型から継承をオーバーライドできません。However, a non-compliant type cannot have compliant members, so you cannot use the attribute with an isCompliant value of true to override inheritance from a non-compliant type.

コンポーネントを開発するときは必ず、CLSCompliantAttribute 属性を使用して、アセンブリ、その型、およびそのメンバーが CLS に準拠しているかどうかを指定することをお勧めします。When you are developing components, you should always use the CLSCompliantAttribute attribute to indicate whether your assembly, its types, and its members are CLS-compliant.

CLS 準拠のコンポーネントを作成するには:To create CLS-compliant components:

  1. CLSCompliantAttribute を使用して、CLS 準拠としてアセンブリをマークします。Use the CLSCompliantAttribute to mark you assembly as CLS-compliant.

  2. アセンブリ内の CLS に準拠していない公開された型を、非準拠としてマークします。Mark any publicly exposed types in the assembly that are not CLS-compliant as non-compliant.

  3. CLS 準拠の型の公開されたメンバーを、非準拠としてマークします。Mark any publicly exposed members in CLS-compliant types as non-compliant.

  4. CLS 非準拠メンバーの CLS 準拠の代替を指定します。Provide a CLS-compliant alternative for non-CLS-compliant members.

非準拠の型とメンバーすべてを正常にマークした場合、非準拠の警告は出力されません。If you've successfully marked all your non-compliant types and members, your compiler should not emit any non-compliance warnings. ただし、どのメンバーが CLS に準拠していないかを提示し、CLS 準拠の代替を製品ドキュメントに示すことをお勧めします。However, you should indicate which members are not CLS-compliant and list their CLS-compliant alternatives in your product documentation.

次の例では、CLSCompliantAttribute 属性を使用して、CLS 準拠のアセンブリと、2 つの CLS 非準拠のメンバーを持つ型、CharacterUtilities を定義します。The following example uses the CLSCompliantAttribute attribute to define a CLS-compliant assembly and a type, CharacterUtilities, that has two non-CLS-compliant members. 両メンバーとも CLSCompliant(false) 属性でタグ付けされているので、警告は生成されません。Because both members are tagged with the CLSCompliant(false) attribute, the compiler produces no warnings. また、クラスには、両方のメソッド用の CLS 準拠の代替も用意されています。The class also provides a CLS-compliant alternative for both methods. 通常、CLS 準拠の代替を用意するには、2 つのオーバーロードを ToUTF16 メソッドに追加するだけです。Ordinarily, we would just add two overloads to the ToUTF16 method to provide CLS-compliant alternatives. ただし、戻り値に基づいてメソッドをオーバーロードできないので、CLS 準拠のメソッドの名前は、非準拠のメソッドの名前とは異なります。However, because methods cannot be overloaded based on return value, the names of the CLS-compliant methods are different from the names of the non-compliant methods.

using System;
using System.Text;

[assembly:CLSCompliant(true)]

public class CharacterUtilities
{
   [CLSCompliant(false)] public static ushort ToUTF16(String s)
   {
      s = s.Normalize(NormalizationForm.FormC);
      return Convert.ToUInt16(s[0]);
   }

   [CLSCompliant(false)] public static ushort ToUTF16(Char ch)
   {
      return Convert.ToUInt16(ch); 
   }
      
   // CLS-compliant alternative for ToUTF16(String).
   public static int ToUTF16CodeUnit(String s)
   {
      s = s.Normalize(NormalizationForm.FormC);
      return (int) Convert.ToUInt16(s[0]);
   }

   // CLS-compliant alternative for ToUTF16(Char).
   public static int ToUTF16CodeUnit(Char ch)
   {
      return Convert.ToInt32(ch);
   }

   public bool HasMultipleRepresentations(String s)
   {
      String s1 = s.Normalize(NormalizationForm.FormC);
      return s.Equals(s1);   
   }

   public int GetUnicodeCodePoint(Char ch)
   {
      if (Char.IsSurrogate(ch))
         throw new ArgumentException("ch cannot be a high or low surrogate.");

      return Char.ConvertToUtf32(ch.ToString(), 0);   
   }
   
   public int GetUnicodeCodePoint(Char[] chars)
   {
      if (chars.Length > 2)
         throw new ArgumentException("The array has too many characters.");

      if (chars.Length == 2) {
         if (! Char.IsSurrogatePair(chars[0], chars[1]))
            throw new ArgumentException("The array must contain a low and a high surrogate.");
         else
            return Char.ConvertToUtf32(chars[0], chars[1]);
      }
      else {
         return Char.ConvertToUtf32(chars.ToString(), 0);
      } 
   }
}
Imports System.Text

<Assembly:CLSCompliant(True)>

Public Class CharacterUtilities
   <CLSCompliant(False)> Public Shared Function ToUTF16(s As String) As UShort
      s = s.Normalize(NormalizationForm.FormC)
      Return Convert.ToUInt16(s(0))
   End Function

   <CLSCompliant(False)> Public Shared Function ToUTF16(ch As Char) As UShort
      Return Convert.ToUInt16(ch) 
   End Function
      
   ' CLS-compliant alternative for ToUTF16(String).
   Public Shared Function ToUTF16CodeUnit(s As String) As Integer
      s = s.Normalize(NormalizationForm.FormC)
      Return CInt(Convert.ToInt16(s(0)))
   End Function

   ' CLS-compliant alternative for ToUTF16(Char).
   Public Shared Function ToUTF16CodeUnit(ch As Char) As Integer
      Return Convert.ToInt32(ch)
   End Function

   Public Function HasMultipleRepresentations(s As String) As Boolean
      Dim s1 As String = s.Normalize(NormalizationForm.FormC)
      Return s.Equals(s1)   
   End Function

   Public Function GetUnicodeCodePoint(ch As Char) As Integer
      If Char.IsSurrogate(ch) Then
         Throw New ArgumentException("ch cannot be a high or low surrogate.")
      End If
      Return Char.ConvertToUtf32(ch.ToString(), 0)   
   End Function
   
   Public Function GetUnicodeCodePoint(chars() As Char) As Integer
      If chars.Length > 2 Then
         Throw New ArgumentException("The array has too many characters.")
      End If
      If chars.Length = 2 Then
         If Not Char.IsSurrogatePair(chars(0), chars(1)) Then
            Throw New ArgumentException("The array must contain a low and a high surrogate.")
         Else
            Return Char.ConvertToUtf32(chars(0), chars(1))
         End If
      Else
         Return Char.ConvertToUtf32(chars.ToString(), 0)
      End If 
   End Function            
End Class

ライブラリではなくアプリを開発している場合 (つまり、他のアプリ開発者が使用できる型またはメンバーを公開しない場合)、アプリが使用するプログラム要素は、そのプログラム要素が使用する言語でサポートされていない場合に CLS に準拠する必要があります。If you are developing an app rather than a library (that is, if you aren't exposing types or members that can be consumed by other app developers), the CLS compliance of the program elements that your app consumes are of interest only if your language does not support them. この場合、CLS 非準拠の要素を使用しようとすると、言語コンパイラによってエラーが生成されます。In that case, your language compiler will generate an error when you try to use a non-CLS-compliant element.

言語間の相互運用性Cross-Language Interoperability

言語に依存しないということは、いくつか意味があります。Language independence has a number of possible meanings. たとえば、ある言語で記述された型を、別の言語で記述されたアプリからシームレスに利用することができます。これについては、記事「言語への非依存性、および言語非依存コンポーネント」で説明されています。One meaning, which is discussed in the article Language Independence and Language-Independent Components, involves seamlessly consuming types written in one language from an app written in another language. また、複数の言語で記述されたコードを 1 つの .NET .NET Framework アセンブリにまとめることもできます。ここでは、この点について焦点を当てて説明します。A second meaning, which is the focus of this article, involves combining code written in multiple languages into a single .NET Framework assembly.

次の例では、NumericLib および StringLib という 2 つのクラスを含む Utilities.dll という名前のクラス ライブラリを作成して言語間の相互運用性を示します。The following example illustrates cross-language interoperability by creating a class library named Utilities.dll that includes two classes, NumericLib and StringLib. NumericLib クラスは C# で記述され、StringLib クラスは Visual Basic で記述されています。The NumericLib class is written in C#, and the StringLib class is written in Visual Basic. 以下は StringUtil.vb のソース コードで、ToTitleCase クラスに StringLib という単一のメンバーが含まれます。Here's the source code for StringUtil.vb, which includes a single member, ToTitleCase, in its StringLib class.

Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module StringLib
   Private exclusions As List(Of String) 
   
   Sub New()
      Dim words() As String = { "a", "an", "and", "of", "the" }
      exclusions = New List(Of String)
      exclusions.AddRange(words)
   End Sub
   
   <Extension()> _
   Public Function ToTitleCase(title As String) As String
      Dim words() As String = title.Split() 
      Dim result As String = String.Empty
      
      For ctr As Integer = 0 To words.Length - 1
         Dim word As String = words(ctr)
         If ctr = 0 OrElse Not exclusions.Contains(word.ToLower()) Then
            result += word.Substring(0, 1).ToUpper() + _
                      word.Substring(1).ToLower()
         Else
            result += word.ToLower()
         End If
         If ctr <= words.Length - 1 Then
            result += " "             
         End If   
      Next 
      Return result 
   End Function
End Module

以下は NumberUtil.cs のソース コードで、NumericLib および IsEven という 2 つのメンバーを持つ NearZero クラスを定義しています。Here's the source code for NumberUtil.cs, which defines a NumericLib class that has two members, IsEven and NearZero.

using System;

public static class NumericLib 
{
   public static bool IsEven(this IConvertible number)
   {
      if (number is Byte ||
          number is SByte ||
          number is Int16 ||
          number is UInt16 || 
          number is Int32 || 
          number is UInt32 ||
          number is Int64)
         return Convert.ToInt64(number) % 2 == 0;
      else if (number is UInt64)
         return ((ulong) number) % 2 == 0;
      else
         throw new NotSupportedException("IsEven called for a non-integer value.");
   }
   
   public static bool NearZero(double number)
   {
      return Math.Abs(number) < .00001; 
   }
}

単一のアセンブリに 2 つのクラスをパッケージ化するには、モジュールにコンパイルする必要があります。To package the two classes in a single assembly, you must compile them into modules. Visual Basic のソース コード ファイルをモジュールにコンパイルするには、次のコマンドを使用します。To compile the Visual Basic source code file into a module, use this command:

vbc /t:module StringUtil.vb

Visual Basic コンパイラのコマンド ライン構文の詳細については、「コマンド ラインからのビルド」を参照してください。For more information about the command-line syntax of the Visual Basic compiler, see Building from the Command Line.

C# のソース コード ファイルをモジュールにコンパイルするには、次のコマンドを使用します。To compile the C# source code file into a module, use this command:

csc /t:module NumberUtil.cs

C# コンパイラのコマンド ライン構文の詳細については、「csc.exe を使用したコマンド ラインからのビルド」を参照してください。For more information about the command-line syntax of the C# compiler, see Command-line Building With csc.exe.

次に、リンカー オプションを使用して 2 つのモジュールをアセンブリにコンパイルします。You then use the Linker options to compile the two modules into an assembly:

link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll

次の例では、その後 NumericLib.NearZero メソッドおよび StringLib.ToTitleCase メソッドを呼び出します。The following example then calls the NumericLib.NearZero and StringLib.ToTitleCase methods. Visual Basic コードと C# コードは、両方のクラスのメソッドにアクセスできることに注意してください。Note that both the Visual Basic code and the C# code are able to access the methods in both classes.

using System;

public class Example
{
   public static void Main()
   {
      Double dbl = 0.0 - Double.Epsilon;
      Console.WriteLine(NumericLib.NearZero(dbl));
      
      string s = "war and peace";
      Console.WriteLine(s.ToTitleCase());
   }
}
// The example displays the following output:
//       True
//       War and Peace
Module Example
   Public Sub Main()
      Dim dbl As Double = 0.0 - Double.Epsilon
      Console.WriteLine(NumericLib.NearZero(dbl))
      
      Dim s As String = "war and peace"
      Console.WriteLine(s.ToTitleCase())
   End Sub
End Module
' The example displays the following output:
'       True
'       War and Peace

Visual Basic コードをコンパイルするには、次のコマンドを使用します。To compile the Visual Basic code, use this command:

vbc example.vb /r:UtilityLib.dll

C# でコンパイルするには、コンパイラの名前を vbc から csc に変更し、ファイル拡張子を .vb から .cs に変更します。To compile with C#, change the name of the compiler from vbc to csc, and change the file extension from .vb to .cs:

csc example.cs /r:UtilityLib.dll

関連項目See also