Niezależność od języka i elementy niezależne od językaLanguage Independence and Language-Independent Components

.NET Framework jest niezależne od języka.The .NET Framework is language independent. Oznacza to, że jako programista można opracowywać w jednym z wielu języków przeznaczonych dla .NET Framework, takich jak C#, C++/CLI, Eiffel, F #, IronPython, IronRuby, PowerBuilder, Visual Basic, Visual COBOL i Windows PowerShell.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. Można uzyskać dostęp do typów i elementów członkowskich bibliotek klas opracowanych dla .NET Framework bez konieczności znajomości języka, w którym zostały pierwotnie napisane, i bez konieczności przestrzegania jakichkolwiek Konwencji języka oryginalnego.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. Jeśli jesteś deweloperem składnika, dostęp do składnika można uzyskać za pomocą dowolnej aplikacji .NET Framework niezależnie od języka.If you are a component developer, your component can be accessed by any .NET Framework app regardless of its language.

Uwaga

W pierwszej części tego artykułu omówiono Tworzenie składników niezależnych od języka — to znaczy składników, które mogą być używane przez aplikacje, które są zapisywane w dowolnym języku.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. Możesz również utworzyć pojedynczy składnik lub aplikację z kodu źródłowego zapisaną w wielu językach. Zobacz współdziałanie między językami w drugiej części tego artykułu.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.

Aby w pełni współistnieć z innymi obiektami zapisanymi w dowolnym języku, obiekty muszą uwidocznić wywołujących tylko te funkcje, które są wspólne dla wszystkich języków.To fully interact with other objects written in any language, objects must expose to callers only those features that are common to all languages. Ten wspólny zestaw funkcji jest definiowany przez Common Language Specification (CLS), który jest zestawem reguł, które są stosowane do wygenerowanych zestawów.This common set of features is defined by the Common Language Specification (CLS), which is a set of rules that apply to generated assemblies. Common Language Specification jest zdefiniowany w partycji I, klauzule od 7 do 11 w standardzie ECMA-335: Common Language Infrastructure.The Common Language Specification is defined in Partition I, Clauses 7 through 11 of the ECMA-335 Standard: Common Language Infrastructure.

Jeśli składnik jest zgodny z Common Language Specification, gwarantowany jest zgodność ze specyfikacją CLS i można uzyskać do niego dostęp z kodu w zestawach pisanych w dowolnym języku programowania, który obsługuje specyfikację 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. Można określić, czy składnik jest zgodny z Common Language Specification w czasie kompilacji, stosując CLSCompliantAttribute atrybut do kodu źródłowego.You can determine whether your component conforms to the Common Language Specification at compile time by applying the CLSCompliantAttribute attribute to your source code. Aby uzyskać więcej informacji, zobacz atrybut CLSCompliantAttribute.For more information, see The CLSCompliantAttribute attribute.

W tym artykule:In this article:

Reguły zgodności ze specyfikacją CLSCLS compliance rules

W tej sekcji omówiono reguły tworzenia składnika zgodnego ze specyfikacją CLS.This section discusses the rules for creating a CLS-compliant component. Aby uzyskać pełną listę reguł, zobacz partycja I, klauzula 11 wzorca ECMA-335: Common Language Infrastructure.For a complete list of rules, see Partition I, Clause 11 of the ECMA-335 Standard: Common Language Infrastructure.

Uwaga

W Common Language Specification omówiono każdą zasadę zgodności ze specyfikacją CLS, która ma zastosowanie do konsumentów (deweloperzy, którzy korzystają z programistycznego dostępu do składnika, który jest zgodny ze specyfikacją CLS), platformy (deweloperzy, którzy używają kompilatora języka do tworzenia bibliotek zgodnych ze standardem ",") i rozszerzeń (deweloperzy, którzy tworzą narzędzia, takie jak kompilator języka lub parser kodu, który tworzy składniki zgodne ze specyfikacjThe 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). Ten artykuł koncentruje się na regułach, które mają zastosowanie do struktur.This article focuses on the rules as they apply to frameworks. Należy zauważyć, że niektóre reguły, które mają zastosowanie do rozszerzeń, mogą również być stosowane do zestawów, które są tworzone za pomocą odbicia. Emituj.Note, though, that some of the rules that apply to extenders may also apply to assemblies that are created using Reflection.Emit.

Aby zaprojektować składnik niezależny od języka, należy zastosować reguły zgodności ze specyfikacją CLS dla interfejsu publicznego składnika.To design a component that is language independent, you only need to apply the rules for CLS compliance to your component's public interface. Twoja prywatna implementacja nie musi być zgodna ze specyfikacją.Your private implementation does not have to conform to the specification.

Ważne

Reguły zgodności ze specyfikacją CLS mają zastosowanie tylko do interfejsu publicznego składnika, a nie do prywatnej implementacji.The rules for CLS compliance apply only to a component's public interface, not to its private implementation.

Na przykład liczba całkowita bez znaku Byte jest niezgodna ze specyfikacją CLS.For example, unsigned integers other than Byte are not CLS-compliant. Ponieważ Person Klasa w poniższym przykładzie uwidacznia Age Właściwość typu UInt16 , poniższy kod wyświetla ostrzeżenie kompilatora.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
'                                ~~~

Można uczynić Person klasę CLS zgodną z, zmieniając typ Age właściwości z UInt16 na Int16 , która jest zgodna ze specyfikacją CLS, 16-bitową liczbą całkowitą ze znakiem.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. Nie trzeba zmieniać typu personAge pola prywatnego.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

Interfejs publiczny biblioteki składa się z następujących elementów:A library's public interface consists of the following:

  • Definicje klas publicznych.Definitions of public classes.

  • Definicje publicznych członków klas publicznych oraz definicje członków dostępnych dla klas pochodnych (czyli chronionych elementów członkowskich).Definitions of the public members of public classes, and definitions of members accessible to derived classes (that is, protected members).

  • Parametry i zwracane typy metod publicznych klas publicznych oraz parametry i zwracane typy metod dostępnych dla klas pochodnych.Parameters and return types of public methods of public classes, and parameters and return types of methods accessible to derived classes.

Reguły zgodności ze specyfikacją CLS są wymienione w poniższej tabeli.The rules for CLS compliance are listed in the following table. Tekst reguł jest pobierany Verbatim z standardu ECMA-335: Common Language Infrastructure, czyli Copyright 2012 przez Ecma International.The text of the rules is taken verbatim from the ECMA-335 Standard: Common Language Infrastructure, which is Copyright 2012 by Ecma International. Bardziej szczegółowe informacje o tych regułach znajdują się w poniższych sekcjach.More detailed information about these rules is found in the following sections.

KategoriaCategory ZobaczSee RegułaRule Numer regułyRule number
Ułatwienia dostępuAccessibility Ułatwienia dostępu członkówMember accessibility Dostępność nie zmienia się podczas zastępowania metod dziedziczonych, z wyjątkiem sytuacji, gdy zastąpi metodę dziedziczoną z innego zestawu z ułatwieniami dostępu 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. W takim przypadku przesłonięcie ma dostęp family .In this case, the override shall have accessibility family. 1010
Ułatwienia dostępuAccessibility Ułatwienia dostępu członkówMember accessibility Widoczność i dostępność typów i członków jest taka, że typy w podpisie każdego elementu członkowskiego są widoczne i dostępne za każdym razem, gdy sam element członkowski jest widoczny i dostępny.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. Na przykład metoda publiczna widoczna poza jej zestawem nie ma argumentu, którego typ jest widoczny tylko w obrębie zestawu.For example, a public method that is visible outside its assembly shall not have an argument whose type is visible only within the assembly. Widoczność i dostępność typów tworzących typ ogólny, używany w podpisie dowolnego elementu członkowskiego, są widoczne i dostępne za każdym razem, gdy element członkowski jest widoczny i dostępny.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. Na przykład typ generyczny skonkretyzowany obecny w sygnaturze elementu członkowskiego, który jest widoczny poza jego zestawem, nie powinien mieć argumentu ogólnego, którego typ jest widoczny tylko w obrębie zestawu.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
TabliceArrays TabliceArrays Tablice powinny mieć elementy z typem zgodnym ze specyfikacją CLS, a wszystkie wymiary tablicy mają dolne granice równe zero.Arrays shall have elements with a CLS-compliant type, and all dimensions of the array shall have lower bounds of zero. Tylko fakt, że element jest tablicą, a typ elementu tablicy musi być wymagany do rozróżnienia między przeciążeniami.Only the fact that an item is an array and the element type of the array shall be required to distinguish between overloads. W przypadku przeciążania opartego na co najmniej dwóch typach tablic typy elementów muszą być nazwanymi typami.When overloading is based on two or more array types the element types shall be named types. 1616
AtrybutyAttributes AtrybutyAttributes Atrybuty są typu System.Attribute lub dziedziczą z niego typ.Attributes shall be of type System.Attribute, or a type inheriting from it. 4141
AtrybutyAttributes AtrybutyAttributes CLS zezwala tylko na podzbiór kodowań atrybutów niestandardowych.The CLS only allows a subset of the encodings of custom attributes. Jedyne typy, które są wyświetlane w tych kodowaniach, to (zobacz partycja IV):,,,,,,,,,, System.Type System.String System.Char System.Boolean System.Byte System.Int16 System.Int32 System.Int64 System.Single System.Double i dowolny typ wyliczeniowy na podstawie typu liczby całkowitej zgodnej ze specyfikacją 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
AtrybutyAttributes AtrybutyAttributes Specyfikacja CLS nie zezwala na jawne widoczne Modyfikatory ( modreq , zobacz partycja II), ale zezwala na Modyfikatory opcjonalne ( modopt , zobacz partycja II), które nie są zrozumiałe.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
KonstruktoryConstructors KonstruktorówConstructors Konstruktor obiektu wywołuje niektórych konstruktorów wystąpień swojej klasy podstawowej przed wszelkimi dostępami do dziedziczonych danych wystąpienia.An object constructor shall call some instance constructor of its base class before any access occurs to inherited instance data. (Nie dotyczy to typów wartości, które nie muszą mieć konstruktorów).(This does not apply to value types, which need not have constructors.) 2121
KonstruktoryConstructors KonstruktorówConstructors Konstruktor obiektów nie jest wywoływany, chyba że jest częścią tworzenia obiektu, a obiekt nie zostanie dwukrotnie zainicjowany.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
WyliczeniaEnumerations WyliczeniaEnumerations Podstawowy typ wyliczenia musi być wbudowanym typem Integer CLS, nazwa pola powinna mieć wartość "value__" i to pole powinno być oznaczone 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
WyliczeniaEnumerations WyliczeniaEnumerations Istnieją dwa odrębne rodzaje wyliczeń, wskazywane przez obecność lub brak System.FlagsAttribute atrybutu niestandardowego (Zobacz Biblioteka partycji IV).There are two distinct kinds of enums, indicated by the presence or absence of the System.FlagsAttribute (see Partition IV Library) custom attribute. Jeden reprezentuje nazwane wartości całkowite; Druga reprezentuje nazwane flagi bitowe, które można połączyć w celu wygenerowania nienazwanej wartości.One represents named integer values; the other represents named bit flags that can be combined to generate an unnamed value. Wartość elementu enum nie jest ograniczona do określonych wartości.The value of an enum is not limited to the specified values. 88
WyliczeniaEnumerations WyliczeniaEnumerations Literałowe pola statyczne typu wyliczeniowego mają typ wyliczenia.Literal static fields of an enum shall have the type of the enum itself. 99
ZdarzeniaEvents ZdarzeniaEvents Metody implementujące zdarzenie należy oznaczyć SpecialName w metadanych.The methods that implement an event shall be marked SpecialName in the metadata. 2929
ZdarzeniaEvents ZdarzeniaEvents Dostępność zdarzenia i jego metod dostępu powinna być taka sama.The accessibility of an event and of its accessors shall be identical. 3030
ZdarzeniaEvents ZdarzeniaEvents addMetody i remove dla zdarzenia muszą być obecne lub nieobecne.The add and remove methods for an event shall both either be present or absent. 3131
ZdarzeniaEvents ZdarzeniaEvents addMetody i remove dla zdarzenia muszą przyjmować jeden parametr, którego typ definiuje typ zdarzenia i który powinien pochodzić od 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
ZdarzeniaEvents ZdarzeniaEvents Zdarzenia muszą być zgodne z określonym wzorcem nazewnictwa.Events shall adhere to a specific naming pattern. SpecialNameAtrybut określony w regule CLS 29 jest ignorowany w odpowiednich porównaniach nazw i przestrzega zasad identyfikatora.The SpecialName attribute referred to in CLS rule 29 shall be ignored in appropriate name comparisons and shall adhere to identifier rules. 3333
WyjątkiExceptions WyjątkiExceptions Obiekty, które są generowane, są typu System.Exception lub dziedziczą z niego typ.Objects that are thrown shall be of type System.Exception or a type inheriting from it. Niemniej jednak metody zgodne ze specyfikacją CLS nie są wymagane do blokowania propagacji innych typów wyjątków.Nonetheless, CLS-compliant methods are not required to block the propagation of other types of exceptions. 4040
OgólneGeneral Zgodność ze specyfikacją CLS: regułyCLS compliance: the Rules Reguły CLS stosują się tylko do tych części typu, które są dostępne lub widoczne poza zestawem definiującym.CLS rules apply only to those parts of a type that are accessible or visible outside of the defining assembly. 11
OgólneGeneral Zgodność ze specyfikacją CLS: regułyCLS compliance: the Rules Elementy członkowskie typów niezgodnych ze specyfikacją CLS nie mogą być oznaczone jako zgodne ze specyfikacją CLS.Members of non-CLS compliant types shall not be marked CLS-compliant. 22
Typy ogólneGenerics Typy ogólne i elementy członkowskieGeneric types and members Zagnieżdżone typy powinny zawierać co najmniej tyle parametrów ogólnych jak typ otaczający.Nested types shall have at least as many generic parameters as the enclosing type. Parametry ogólne w typie zagnieżdżonym odpowiadają pozycjom parametrów ogólnych w jego typie otaczającym.Generic parameters in a nested type correspond by position to the generic parameters in its enclosing type. 4242
Typy ogólneGenerics Typy ogólne i elementy członkowskieGeneric types and members Nazwa typu ogólnego zawiera kodowanie liczby parametrów typu zadeklarowanych w typie niezagnieżdżonym lub nowo wprowadzona do typu, jeśli jest zagnieżdżona, zgodnie z regułami określonymi powyżej.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
Typy ogólneGenerics Typy ogólne i elementy członkowskieGeneric types and members Typ ogólny musi redeklarować wystarczające ograniczenia, aby zagwarantować, że wszystkie ograniczenia dotyczące typu podstawowego lub interfejsów byłyby spełnione przez ograniczenia typu ogólnego.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
Typy ogólneGenerics Typy ogólne i elementy członkowskieGeneric types and members Typy używane jako ograniczenia parametrów ogólnych będą same w sobie zgodne ze specyfikacją CLS.Types used as constraints on generic parameters shall themselves be CLS-compliant. 4545
Typy ogólneGenerics Typy ogólne i elementy członkowskieGeneric types and members Widoczność i dostępność elementów członkowskich (w tym zagnieżdżonych typów) w typie ogólnym, który można utworzyć, jest uznawana za zakres do określonego wystąpienia, a nie jako całości deklaracji typu ogólnego.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. Przy założeniu, że nadal mają zastosowanie reguły widoczności i dostępności reguły CLS 12.Assuming this, the visibility and accessibility rules of CLS rule 12 still apply. 4646
Typy ogólneGenerics Typy ogólne i elementy członkowskieGeneric types and members Dla każdej abstrakcyjnej lub wirtualnej metody ogólnej należy mieć domyślną implementację specyficzną (nieabstrakcyjną).For each abstract or virtual generic method, there shall be a default concrete (non-abstract) implementation. 4747
InterfejsyInterfaces InterfejsyInterfaces Interfejsy zgodne ze specyfikacją CLS nie wymagają definicji metod niezgodnych ze specyfikacją CLS w celu ich wdrożenia.CLS-compliant interfaces shall not require the definition of non-CLS compliant methods in order to implement them. 1818
InterfejsyInterfaces InterfejsyInterfaces Interfejsy zgodne ze specyfikacją CLS nie definiują metod statycznych ani nie definiują pól.CLS-compliant interfaces shall not define static methods, nor shall they define fields. 1919
Elementy członkowskieMembers Ogólnie wpisz składoweType members in general Globalne pola statyczne i metody nie są zgodne ze specyfikacją CLS.Global static fields and methods are not CLS-compliant. 3636
Elementy członkowskieMembers -- Wartość literału statycznego jest określana za pomocą metadanych inicjacji pola.The value of a literal static is specified through the use of field initialization metadata. Literał zgodny ze specyfikacją CLS musi mieć wartość określoną w metadanych inicjowania pola, które są dokładnie takie same jak w przypadku literału (lub typu podstawowego, jeśli ten literał to 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
Elementy członkowskieMembers Ogólnie wpisz składoweType members in general Ograniczenie vararg nie jest częścią specyfikacji CLS, a jedyną konwencją wywoływania obsługiwaną przez specyfikację CLS jest standardowa zarządzana Konwencja wywoływania.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
Konwencje nazewnictwaNaming conventions Konwencje nazewnictwaNaming conventions Zespoły muszą stosować się do załącznika 7 raportu technicznego 15 standardu Unicode 3.0 w celu określenia zestawu znaków, które mogą być uruchamiane i uwzględniane w identyfikatorach, dostępne online na stronie 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. Identyfikatory powinny znajdować się w formacie kanonicznym zdefiniowanym przez normalizację Unicode w postaci C. W celach CLS dwa identyfikatory są takie same, jeśli ich mapowania małymi literami (zgodnie z ustawieniami regionalnymi Unicode, które różnią się od liter, jeden do jednego) są takie same.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. Oznacza to, że w przypadku dwóch identyfikatorów, które mają być uznawane za różne pod względem CLS, różnią się w więcej niż w ich przypadku.That is, for two identifiers to be considered different under the CLS they shall differ in more than simply their case. Jednak w celu zastąpienia definicji dziedziczonej, interfejs wiersza polecenia wymaga dokładnego kodowania oryginalnej deklaracji.However, in order to override an inherited definition the CLI requires the precise encoding of the original declaration be used. 44
PrzeciążenieOverloading Konwencje nazewnictwaNaming conventions Wszystkie nazwy wprowadzone w zakresie zgodnym ze specyfikacją CLS powinny być odrębne niezależnie od rodzaju, z wyjątkiem sytuacji, gdy nazwy są identyczne i rozwiązywane przez przeciążanie.All names introduced in a CLS-compliant scope shall be distinct independent of kind, except where the names are identical and resolved via overloading. Oznacza to, że podczas CTSallows jednego typu do używania tej samej nazwy dla metody i pola, CLS nie.That is, while the CTSallows a single type to use the same name for a method and a field, the CLS does not. 55
PrzeciążenieOverloading Konwencje nazewnictwaNaming conventions Pola i zagnieżdżone typy powinny różnić się odrębnie przez porównanie identyfikatorów, nawet jeśli CTS zezwala na rozróżnianie unikatowych podpisów.Fields and nested types shall be distinct by identifier comparison alone, even though the CTS allows distinct signatures to be distinguished. Metody, właściwości i zdarzenia, które mają taką samą nazwę (za pomocą porównania identyfikatorów), różnią się więcej niż tylko zwracanym typem, z wyjątkiem określonych w regule 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
PrzeciążenieOverloading PrzeciążeniaOverloads Tylko właściwości i metody mogą być przeciążone.Only properties and methods can be overloaded. 3737
PrzeciążenieOverloading PrzeciążeniaOverloads Właściwości i metody mogą być przeciążone na podstawie liczby i typów ich parametrów, z wyjątkiem operatorów konwersji o nazwach op_Implicit i op_Explicit , które mogą być również przeciążone na podstawie ich typu zwracanego.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
PrzeciążenieOverloading -- Jeśli dwie lub więcej metod zgodnych ze specyfikacją CLS zadeklarowanych w typie ma taką samą nazwę i, dla określonego zestawu wystąpień typu, mają one te same parametry i zwracane typy, wówczas wszystkie te metody są semantycznie równoważne w tych wystąpieniach typu.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
TypyTypes Typ i podpisy elementów członkowskich typuType and type member signatures System.Objectjest zgodny ze specyfikacją CLS.System.Object is CLS-compliant. Wszystkie inne klasy zgodne ze specyfikacją CLS są dziedziczone z klasy zgodnej ze specyfikacją CLS.Any other CLS-compliant class shall inherit from a CLS-compliant class. 2323
WłaściwościProperties WłaściwościProperties Metody, które implementują metody pobierającej i ustawiającej właściwość, powinny być oznaczone SpecialName w metadanych.The methods that implement the getter and setter methods of a property shall be marked SpecialName in the metadata. 2424
WłaściwościProperties WłaściwościProperties Metody dostępu do właściwości muszą być statyczne, wszystkie być wirtualne lub być wystąpieniem.A property’s accessors shall all be static, all be virtual, or all be instance. 2626
WłaściwościProperties WłaściwościProperties Typ właściwości musi być typem zwracanym metody pobierającej i typem ostatniego argumentu metody ustawiającej.The type of a property shall be the return type of the getter and the type of the last argument of the setter. Typy parametrów właściwości są typami parametrów do metody pobierającej i typami wszystkich oprócz końcowych parametrów metody ustawiającej.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. Wszystkie te typy muszą być zgodne ze specyfikacją CLS i nie mogą być wskaźnikami zarządzanymi (tj. nie są przesyłane przez odwołanie).All of these types shall be CLS-compliant, and shall not be managed pointers (i.e., shall not be passed by reference). 2727
WłaściwościProperties WłaściwościProperties Właściwości muszą być zgodne z określonym wzorcem nazewnictwa.Properties shall adhere to a specific naming pattern. SpecialNameAtrybut, do którego odwołuje się reguła CLS, jest ignorowany w odpowiednich porównaniach nazw i przestrzega reguł identyfikatorów.The SpecialName attribute referred to in CLS rule 24 shall be ignored in appropriate name comparisons and shall adhere to identifier rules. Właściwość ma metodę pobierającą, metodę ustawiającą lub obie te metody.A property shall have a getter method, a setter method, or both. 2828
Konwersja typuType conversion Konwersja typuType conversion Jeśli op_Implicit lub op_Explicit jest podany, należy podać alternatywny sposób przekazywania przekształcenie.If either op_Implicit or op_Explicit is provided, an alternate means of providing the coercion shall be provided. 3939
TypyTypes Typ i podpisy elementów członkowskich typuType and type member signatures Opakowane typy wartości nie są zgodne ze specyfikacją CLS.Boxed value types are not CLS-compliant. 33
TypyTypes Typ i podpisy elementów członkowskich typuType and type member signatures Wszystkie typy występujące w podpisie muszą być zgodne ze specyfikacją CLS.All types appearing in a signature shall be CLS-compliant. Wszystkie typy tworzące typ ogólny, który tworzy wystąpienie, są zgodne ze specyfikacją CLS.All types composing an instantiated generic type shall be CLS-compliant. 1111
TypyTypes Typ i podpisy elementów członkowskich typuType and type member signatures Wpisane odwołania nie są zgodne ze specyfikacją CLS.Typed references are not CLS-compliant. 1414
TypyTypes Typ i podpisy elementów członkowskich typuType and type member signatures Niezarządzane typy wskaźnika nie są zgodne ze specyfikacją CLS.Unmanaged pointer types are not CLS-compliant. 1717
TypyTypes Typ i podpisy elementów członkowskich typuType and type member signatures Klasy zgodne ze specyfikacją CLS, typy wartości i interfejsy nie wymagają implementacji członków niezgodnych ze specyfikacją CLS.CLS-compliant classes, value types, and interfaces shall not require the implementation of non-CLS-compliant members. 2020

Typy i podpisy elementów członkowskich typuTypes and type member signatures

System.ObjectTyp jest zgodny ze specyfikacją CLS i jest typem podstawowym wszystkich typów obiektów w systemie .NET Framework typu.The System.Object type is CLS-compliant and is the base type of all object types in the .NET Framework type system. Dziedziczenie w .NET Framework jest niejawne (na przykład String Klasa niejawnie dziedziczy z Object klasy) lub jawna (na przykład klasa dziedziczy jawnie z klasy, która jawnie dziedziczy z klasy, która jawnie dziedziczy z CultureNotFoundException ArgumentException SystemException Exception klasy).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). Aby typ pochodny był zgodny ze specyfikacją CLS, jego typ podstawowy również musi być zgodny ze specyfikacją CLS.For a derived type to be CLS compliant, its base type must also be CLS-compliant.

Poniższy przykład przedstawia typ pochodny, którego typ podstawowy nie jest zgodny ze specyfikacją CLS.The following example shows a derived type whose base type is not CLS-compliant. Definiuje klasę bazową Counter , która używa niepodpisanej 32-bitowej liczby całkowitej jako licznika.It defines a base Counter class that uses an unsigned 32-bit integer as a counter. Ponieważ Klasa udostępnia funkcje licznika przez Zawijanie liczby całkowitej bez znaku, Klasa jest oznaczona jako niezgodna ze specyfikacją CLS.Because the class provides counter functionality by wrapping an unsigned integer, the class is marked as non-CLS-compliant. W związku z tym Klasa pochodna, NonZeroCounter , również nie jest zgodna ze specyfikacją 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
'                 ~~~~~~~~~~~~~~

Wszystkie typy, które pojawiają się w sygnaturach składowych, łącznie z typem zwracanym metody lub typem właściwości, muszą być zgodne ze specyfikacją CLS.All types that appear in member signatures, including a method's return type or a property type, must be CLS-compliant. Ponadto dla typów ogólnych:In addition, for generic types:

  • Wszystkie typy tworzące typ ogólny wystąpienia muszą być zgodne ze specyfikacją CLS.All types that compose an instantiated generic type must be CLS-compliant.

  • Wszystkie typy używane jako ograniczenia parametrów ogólnych muszą być zgodne ze specyfikacją CLS.All types used as constraints on generic parameters must be CLS-compliant.

Wspólny system typów .NET Framework obejmuje wiele wbudowanych typów, które są obsługiwane bezpośrednio przez środowisko uruchomieniowe języka wspólnego i są specjalnie kodowane w metadanych zestawu.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. Z tych typów wewnętrznych typy wymienione w poniższej tabeli są zgodne ze specyfikacją CLS.Of these intrinsic types, the types listed in the following table are CLS-compliant.

Typ zgodny ze specyfikacją CLSCLS-compliant type OpisDescription
Byte 8-bitowa liczba całkowita bez znaku8-bit unsigned integer
Int16 16-bitowa liczba całkowita ze znakiem16-bit signed integer
Int32 32-bitowa liczba całkowita ze znakiem32-bit signed integer
Int64 64-bitowa liczba całkowita ze znakiem64-bit signed integer
Single Wartość zmiennoprzecinkowa o pojedynczej precyzjiSingle-precision floating-point value
Double Wartość zmiennoprzecinkowa o podwójnej precyzjiDouble-precision floating-point value
Boolean truelub false Typ wartościtrue or false value type
Char Jednostka kodu zakodowana w formacie UTF-16UTF-16 encoded code unit
Decimal Liczba dziesiętna liczb zmiennoprzecinkowychNon-floating-point decimal number
IntPtr Wskaźnik lub uchwyt rozmiaru zdefiniowanego przez platformęPointer or handle of a platform-defined size
String Kolekcja zero, jeden lub więcej Char obiektówCollection of zero, one, or more Char objects

Typy wewnętrzne wymienione w poniższej tabeli są niezgodne ze specyfikacją CLS.The intrinsic types listed in the following table are not CLS-Compliant.

Niezgodny typNon-compliant type OpisDescription Alternatywa zgodna ze specyfikacją CLSCLS-compliant alternative
SByte 8-bitowy typ danych ze znakiem liczb całkowitych8-bit signed integer data type Int16
TypedReference Wskaźnik do obiektu i jego typu środowiska uruchomieniowegoPointer to an object and its runtime type BrakNone
UInt16 16-bitowa liczba całkowita bez znaku16-bit unsigned integer Int32
UInt32 32-bitowa liczba całkowita bez znaku32-bit unsigned integer Int64
UInt64 64-bitowa liczba całkowita bez znaku64-bit unsigned integer Int64(może przepełnić się), BigInteger lubDoubleInt64 (may overflow), BigInteger, or Double
UIntPtr Niepodpisany wskaźnik lub dojścieUnsigned pointer or handle IntPtr

Biblioteka klas .NET Framework lub jakakolwiek inna Biblioteka klas może zawierać inne typy, które nie są zgodne ze specyfikacją CLS; na przykład:The .NET Framework Class Library or any other class library may include other types that aren't CLS-compliant; for example:

  • Opakowane typy wartości.Boxed value types. Poniższy przykład w języku C# tworzy klasę, która ma właściwość publiczną typu int* o nazwie Value .The following C# example creates a class that has a public property of type int* named Value. Ponieważ int* jest to opakowany typ wartości, kompilator flaguje go jako niezgodny ze specyfikacją 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
    
  • Typy odwołań, które są specjalnymi konstrukcjami, które zawierają odwołanie do obiektu i odwołanie do typu.Typed references, which are special constructs that contain a reference to an object and a reference to a type. Wpisane odwołania są reprezentowane w .NET Framework przez TypedReference klasę.Typed references are represented in the .NET Framework by the TypedReference class.

Jeśli typ nie jest zgodny ze specyfikacją CLS, należy zastosować CLSCompliantAttribute atrybut z isCompliant wartością false do.If a type is not CLS-compliant, you should apply the CLSCompliantAttribute attribute with an isCompliant value of false to it. Aby uzyskać więcej informacji, zobacz sekcję atrybut CLSCompliantAttribute .For more information, see The CLSCompliantAttribute attribute section.

Poniższy przykład ilustruje problem zgodności ze specyfikacją CLS w sygnaturze metody i w tworzeniu wystąpienia typu ogólnego.The following example illustrates the problem of CLS compliance in a method signature and in generic type instantiation. Definiuje InvoiceItem klasę z właściwością typu UInt32 , właściwością typu Nullable(Of UInt32) i konstruktorem z parametrami typu UInt32 i Nullable(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). Podczas próby skompilowania tego przykładu uzyskasz cztery ostrzeżenia kompilatora.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
'                       ~~~~~~~~~

Aby wyeliminować ostrzeżenia kompilatora, Zastąp typy niezgodne ze specyfikacją CLS w InvoiceItem interfejsie publicznym przy użyciu zgodnych typów: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

Oprócz określonych typów wymienionych niektóre kategorie typów nie są zgodne ze specyfikacją CLS.In addition to the specific types listed, some categories of types are not CLS compliant. Są to między innymi typy wskaźników niezarządzanych i typy wskaźników funkcji.These include unmanaged pointer types and function pointer types. Poniższy przykład generuje ostrzeżenie kompilatora, ponieważ używa wskaźnika do liczby całkowitej, aby utworzyć tablicę liczb całkowitych.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

Dla klas abstrakcyjnych zgodnych ze specyfikacją CLS (czyli klas oznaczonych jako abstract w języku C# lub MustInherit w Visual Basic) wszystkie elementy członkowskie klasy muszą również być zgodne ze specyfikacją 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.

Konwencje nazewnictwaNaming conventions

Ponieważ w niektórych językach programowania nie jest rozróżniana wielkość liter, identyfikatory (takie jak nazwy przestrzeni nazw, typy i składowe) muszą różnić się więcej niż wielkością liter.Because some programming languages are case-insensitive, identifiers (such as the names of namespaces, types, and members) must differ by more than case. Dwa identyfikatory są uważane za równoważne, jeśli ich mapowania małych liter są takie same.Two identifiers are considered equivalent if their lowercase mappings are the same. Poniższy przykład języka C# definiuje dwie klasy publiczne Person i person .The following C# example defines two public classes, Person and person. Ponieważ różnią się tylko wielkością liter, kompilator języka C# flaguje je jako niezgodne ze specyfikacją 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)

Identyfikatory języków programowania, takie jak nazwy przestrzeni nazw, typy i elementy członkowskie, muszą być zgodne ze standardem Unicode 3,0, sprawozdanie techniczne 15, załącznik 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. Oznacza to, że:This means that:

  • Pierwszy znak identyfikatora może być dowolną wielką literą Unicode, małą literą, literą litery tytułu, literą modyfikującą, inną literą lub cyfrą.The first character of an identifier can be any Unicode uppercase letter, lowercase letter, title case letter, modifier letter, other letter, or letter number. Aby uzyskać informacje dotyczące kategorii znaków Unicode, zobacz System.Globalization.UnicodeCategory Wyliczenie.For information on Unicode character categories, see the System.Globalization.UnicodeCategory enumeration.

  • Kolejne znaki mogą pochodzić z dowolnej kategorii jako pierwszy znak i mogą również zawierać znaczniki niebędące odstępami, odstępy łączące znaczniki, liczby dziesiętne, interpunkcji łącznika i kody formatowania.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.

Przed porównaniem identyfikatorów należy odfiltrować kody formatowania i przekonwertować identyfikatory na postać normalizacji Unicode, ponieważ pojedynczy znak może być reprezentowany przez wiele jednostek kodu zakodowanych w formacie 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. Sekwencje znaków tworzące te same jednostki kodu w formularzu normalizacji Unicode nie są zgodne ze specyfikacją CLS.Character sequences that produce the same code units in Unicode Normalization Form C are not CLS-compliant. W poniższym przykładzie zdefiniowano właściwość o nazwie , która składa się ze znaku Angstrom znak (U + 212B), a druga właściwość o nazwie Å , która składa się z znaku Wielka litera a z pierścieniem powyżej (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). Kompilatory C# i Visual Basic będą flagować kod źródłowy jako niezgodny ze specyfikacją 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
'                       ~

Nazwy elementów członkowskich w ramach określonego zakresu (takie jak przestrzenie nazw w obrębie zestawu, typy w przestrzeni nazw lub elementy członkowskie w ramach typu) muszą być unikatowe, z wyjątkiem nazw, które są rozpoznawane za pomocą przeciążenia.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. To wymaganie jest bardziej rygorystyczne niż w przypadku systemu wspólnego typu, który umożliwia wielu członkom w zakresie posiadanie identycznych nazw, o ile są one różnymi rodzajami elementów członkowskich (na przykład jest to metoda, a jedna to pole).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). W szczególności dla elementów członkowskich typu:In particular, for type members:

  • Pola i zagnieżdżone typy są rozróżniane wyłącznie nazwami.Fields and nested types are distinguished by name alone.

  • Metody, właściwości i zdarzenia, które mają taką samą nazwę, muszą różnić się więcej niż tylko zwracanym typem.Methods, properties, and events that have the same name must differ by more than just return type.

Poniższy przykład ilustruje wymaganie, aby nazwy elementów członkowskich muszą być unikatowe w ramach zakresu.The following example illustrates the requirement that member names must be unique within their scope. Definiuje klasę o nazwie Converter , która zawiera cztery składowe o nazwie Conversion .It defines a class named Converter that includes four members named Conversion. Trzy to metody, a jedna jest właściwością.Three are methods, and one is a property. Metoda, która zawiera Int64 parametr, ma unikatową nazwę, ale dwie metody z Int32 parametrem nie są, ponieważ wartość zwracana nie jest uważana za część podpisu elementu członkowskiego.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. ConversionWłaściwość również narusza to wymaganie, ponieważ właściwości nie mogą mieć takiej samej nazwy jak przeciążone metody.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
'                                ~~~~~~~~~~

Poszczególne języki zawierają unikatowe słowa kluczowe, dlatego Języki przeznaczone dla środowiska uruchomieniowego języka wspólnego muszą również zawierać mechanizm odwołujący się do identyfikatorów (takich jak nazwy typów), które pokrywają się ze słowami kluczowymi.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. Na przykład, case jest słowem kluczowym w języku C# i Visual Basic.For example, case is a keyword in both C# and Visual Basic. Jednak poniższy Visual Basic przykład jest w stanie odróżnić klasę o nazwie case od case słowa kluczowego za pomocą otwierającego i zamykającego nawiasu klamrowego.However, the following Visual Basic example is able to disambiguate a class named case from the case keyword by using opening and closing braces. W przeciwnym razie przykład zostanie wyświetlony komunikat o błędzie "słowo kluczowe nie jest prawidłowe jako identyfikator" i nie można go skompilować.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

W poniższym przykładzie w języku C# można utworzyć wystąpienie case klasy przy użyciu @ symbolu, aby odróżnić identyfikator od słowa kluczowego języka.The following C# example is able to instantiate the case class by using the @ symbol to disambiguate the identifier from the language keyword. Bez niej, kompilator języka C# wyświetli dwa komunikaty o błędach, "Oczekiwano typu" i "wyrażenie" nieprawidłowego terminu "."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);
   }
}

Konwersja typuType conversion

Common Language Specification definiuje dwa operatory konwersji:The Common Language Specification defines two conversion operators:

  • op_Implicit, który jest używany do rozszerzania konwersji, które nie powodują utraty danych lub dokładności.op_Implicit, which is used for widening conversions that do not result in loss of data or precision. Na przykład Decimal Struktura zawiera przeciążony operator, op_Implicit aby konwertować wartości typów całkowitych i Char wartości na Decimal wartości.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, który jest używany na potrzeby konwersji zawężających, które mogą spowodować utratę wielkości (wartość jest konwertowana na wartość, która ma mniejszy zakres) lub precyzję.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. Na przykład Decimal Struktura zawiera przeciążony op_Explicit operator do konwersji Double i Single wartości na Decimal i do konwersji wartości do Decimal wartości całkowitych, Double , Single , i 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.

Jednak nie wszystkie języki obsługują przeciążanie operatora lub definicję operatorów niestandardowych.However, not all languages support operator overloading or the definition of custom operators. Jeśli zdecydujesz się zaimplementować te operatory konwersji, należy również podać alternatywny sposób wykonywania konwersji.If you choose to implement these conversion operators, you should also provide an alternate way to perform the conversion. Zalecamy podanie From metod XXX i To XXX .We recommend that you provide FromXxx and ToXxx methods.

W poniższym przykładzie zdefiniowano Konwersje jawne zgodne ze specyfikacją CLS.The following example defines CLS-compliant implicit and explicit conversions. Tworzy UDouble klasę, która reprezentuje podpisaną liczbę zmiennoprzecinkową o podwójnej precyzji.It creates a UDouble class that represents an signed double-precision, floating-point number. Zapewnia to niejawne konwersje z UDouble do Double i dla jawnych konwersji z UDouble do Single , Double do UDouble , i Single do 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. Definiuje również ToDouble metodę jako alternatywę dla operatora niejawnej konwersji oraz ToSingle FromDouble metody,, i FromSingle jako alternatywy dla operatorów jawnej konwersji.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

TabliceArrays

Tablice zgodne ze specyfikacją CLS są zgodne z następującymi regułami:CLS-compliant arrays conform to the following rules:

  • Wszystkie wymiary tablicy muszą mieć dolną granicę równą zero.All dimensions of an array must have a lower bound of zero. Poniższy przykład tworzy tablicę niezgodną ze specyfikacją CLS z dolną granicą.The following example creates a non-CLS-compliant array with a lower bound of one. Należy zauważyć, że pomimo obecności CLSCompliantAttribute atrybutu kompilator nie wykrywa, że tablica zwracana przez Numbers.GetTenPrimes metodę nie jest zgodna ze specyfikacją 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
    
  • Wszystkie elementy tablicy muszą zawierać typy zgodne ze specyfikacją CLS.All array elements must consist of CLS-compliant types. W poniższym przykładzie zdefiniowano dwie metody, które zwracają tablice niezgodne ze specyfikacją CLS.The following example defines two methods that return non-CLS-compliant arrays. Pierwszy zwraca tablicę UInt32 wartości.The first returns an array of UInt32 values. Druga zwraca Object tablicę zawierającą Int32 wartości i UInt32 .The second returns an Object array that includes Int32 and UInt32 values. Chociaż kompilator identyfikuje pierwszą tablicę jako niezgodną ze względu na jej UInt32 Typ, nie rozpoznaje, że druga tablica zawiera elementy niezgodne ze specyfikacją 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()
    '                              ~~~~~~~~~~~~
    
  • Rozpoznawanie przeciążenia dla metod, które mają parametry tablicowe, jest oparte na faktach, że są tablicami i według ich typu elementu.Overload resolution for methods that have array parameters is based on the fact that they are arrays and on their element type. Z tego powodu następująca definicja przeciążonej GetSquares metody jest zgodna ze specyfikacją 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
    

InterfejsyInterfaces

Interfejsy zgodne ze specyfikacją CLS mogą definiować właściwości, zdarzenia i metody wirtualne (metody bez implementacji).CLS-compliant interfaces can define properties, events, and virtual methods (methods with no implementation). Interfejs zgodny ze specyfikacją CLS nie może mieć następujących elementów:A CLS-compliant interface cannot have any of the following:

  • Metody statyczne lub pola statyczne.Static methods or static fields. Kompilatory C# i Visual Basic generują błędy kompilatora, jeśli zdefiniujesz statyczną składową w interfejsie.Both the C# and Visual Basic compilers generate compiler errors if you define a static member in an interface.

  • Pola.Fields. Kompilatory C# i Visual Basic generują błędy kompilatora, jeśli zdefiniujesz pole w interfejsie.Both the C# and Visual Basic compilers generate compiler errors if you define a field in an interface.

  • Metody, które nie są zgodne ze specyfikacją CLS.Methods that are not CLS-compliant. Na przykład następująca definicja interfejsu obejmuje metodę, INumber.GetUnsigned która jest oznaczona jako niezgodna ze specyfikacją CLS.For example, the following interface definition includes a method, INumber.GetUnsigned, that is marked as non-CLS-compliant. Ten przykład generuje ostrzeżenie kompilatora.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
    '                                      ~~~~~~~~~~~
    

    Ze względu na tę regułę typy zgodne ze specyfikacją CLS nie są wymagane do implementacji członków niezgodnych ze specyfikacją CLS.Because of this rule, CLS-compliant types are not required to implement non-CLS-compliant members. Jeśli struktura zgodna ze specyfikacją CLS uwidacznia klasę, która implementuje interfejs niezgodny ze specyfikacją CLS, powinien również udostępnić konkretne implementacje wszystkich członków niezgodnych ze specyfikacją 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.

Kompilatory języka zgodne ze specyfikacją CLS muszą również zezwalać klasie na udostępnianie oddzielnych implementacji elementów członkowskich o tej samej nazwie i podpisie w wielu interfejsach.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. Języki C# i Visual Basic obsługują jawne implementacje interfejsu w celu zapewnienia różnych implementacji identycznie nazwanych metod.Both C# and Visual Basic support explicit interface implementations to provide different implementations of identically named methods. Visual Basic obsługuje również Implements słowo kluczowe, które umożliwia jawne wyznaczanie interfejsów i elementów członkowskich implementujących określony element członkowski.Visual Basic also supports the Implements keyword, which enables you to explicitly designate which interface and member a particular member implements. Poniższy przykład ilustruje ten scenariusz, definiując Temperature klasę implementującą ICelsius IFahrenheit interfejsy i jako jawne implementacje interfejsu.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

WyliczeniaEnumerations

Wyliczenia zgodne ze specyfikacją CLS muszą być zgodne z następującymi regułami:CLS-compliant enumerations must follow these rules:

  • Podstawowym typem wyliczenia musi być wewnętrzna liczba całkowita zgodna ze specyfikacją CLS ( Byte , Int16 , Int32 lub Int64 ).The underlying type of the enumeration must be an intrinsic CLS-compliant integer (Byte, Int16, Int32, or Int64). Na przykład poniższy kod próbuje zdefiniować Wyliczenie, którego typ podstawowy jest UInt32 i generuje ostrzeżenie kompilatora.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
    '                ~~~~
    
  • Typ wyliczenia musi mieć jedno pole wystąpienia o nazwie Value__ , które jest oznaczone FieldAttributes.RTSpecialName atrybutem.An enumeration type must have a single instance field named Value__ that is marked with the FieldAttributes.RTSpecialName attribute. Dzięki temu można odwołać się do wartości pola niejawnie.This enables you to reference the field value implicitly.

  • Wyliczenie zawiera literał pól statycznych, których typy pasują do typu wyliczenia.An enumeration includes literal static fields whose types match the type of the enumeration itself. Na przykład, jeśli zdefiniujesz State Wyliczenie z wartościami State.On i State.Off , State.On i State.Off są polami literałów statycznych, których typem jest 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.

  • Istnieją dwa rodzaje wyliczeń:There are two kinds of enumerations:

    • Wyliczenie, które reprezentuje zestaw wzajemnie wykluczających się wartości o nazwach całkowitych.An enumeration that represents a set of mutually exclusive, named integer values. Ten typ wyliczenia jest wskazywany przez brak System.FlagsAttribute atrybutu niestandardowego.This type of enumeration is indicated by the absence of the System.FlagsAttribute custom attribute.

    • Wyliczenie, które reprezentuje zestaw flag bitowych, które można połączyć w celu wygenerowania nienazwanej wartości.An enumeration that represents a set of bit flags that can combine to generate an unnamed value. Ten typ wyliczenia jest wskazywany przez obecność System.FlagsAttribute atrybutu niestandardowego.This type of enumeration is indicated by the presence of the System.FlagsAttribute custom attribute.

    Aby uzyskać więcej informacji, zapoznaj się z dokumentacją Enum struktury.For more information, see the documentation for the Enum structure.

  • Wartość wyliczenia nie jest ograniczona do zakresu określonych wartości.The value of an enumeration is not limited to the range of its specified values. Innymi słowy, zakres wartości w wyliczeniu jest zakresem jego wartości źródłowej.In other words, the range of values in an enumeration is the range of its underlying value. Możesz użyć metody, Enum.IsDefined Aby określić, czy określona wartość jest elementem członkowskim wyliczenia.You can use the Enum.IsDefined method to determine whether a specified value is a member of an enumeration.

Ogólnie wpisz składoweType members in general

Common Language Specification wymaga, aby wszystkie pola i metody były dostępne jako elementy członkowskie konkretnej klasy.The Common Language Specification requires all fields and methods to be accessed as members of a particular class. W związku z tym globalne pola i metody statyczne (czyli pola statyczne lub metody, które są zdefiniowane niezależnie od typu) nie są zgodne ze specyfikacją CLS.Therefore, global static fields and methods (that is, static fields or methods that are defined apart from a type) are not CLS-compliant. Jeśli spróbujesz dołączyć pole globalne lub metodę w kodzie źródłowym, kompilatory C# i Visual Basic generują błąd kompilatora.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.

Common Language Specification obsługuje tylko standardową konwencję wywoływania zarządzanego.The Common Language Specification supports only the standard managed calling convention. Nie obsługuje ona niezarządzanych konwencji wywoływania i metod ze zmiennymi listami argumentów oznaczonymi varargs słowem kluczowym.It doesn't support unmanaged calling conventions and methods with variable argument lists marked with the varargs keyword. W przypadku list zmiennych argumentów, które są zgodne ze standardową konwencją wywoływania zarządzanego, użyj ParamArrayAttribute atrybutu lub implementacji poszczególnych języków, takich jak params słowo kluczowe w języku C# i ParamArray słowo kluczowe w Visual Basic.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.

Ułatwienia dostępu członkówMember accessibility

Zastępowanie dziedziczonego elementu członkowskiego nie może zmienić dostępności tego elementu członkowskiego.Overriding an inherited member cannot change the accessibility of that member. Na przykład metoda publiczna w klasie bazowej nie może zostać zastąpiona przez prywatną metodę w klasie pochodnej.For example, a public method in a base class cannot be overridden by a private method in a derived class. Istnieje jeden wyjątek: protected internal element członkowski (w języku C#) lub Protected Friend (w Visual Basic) w jednym zestawie, który jest zastępowany przez typ w innym zestawie.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. W takim przypadku dostępność przesłonięcia to Protected .In that case, the accessibility of the override is Protected.

Poniższy przykład ilustruje błąd generowany, gdy CLSCompliantAttribute atrybut jest ustawiony na true , i Human , który jest klasą pochodną Animal , próbuje zmienić dostępność Species właściwości z publicznej na prywatną.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. Przykład został pomyślnie skompilowany, jeśli jego dostępność została zmieniona na publiczną.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

Typy w podpisie składowej muszą być dostępne za każdym razem, gdy ten element członkowski jest dostępny.Types in the signature of a member must be accessible whenever that member is accessible. Na przykład oznacza to, że publiczna składowa nie może zawierać parametru, którego typem jest Private, protected lub internal.For example, this means that a public member cannot include a parameter whose type is private, protected, or internal. Poniższy przykład ilustruje błąd kompilatora, który powstaje, gdy StringWrapper Konstruktor klasy ujawnia wewnętrzną StringOperationType wartość wyliczenia, która określa, jak powinna być opakowana wartość ciągu.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)
'                              ~~~~~~~~~~~~~~~~~~~

Typy ogólne i elementy członkowskieGeneric types and members

Zagnieżdżone typy zawsze mają co najmniej tyle parametrów ogólnych jak ich typ otaczający.Nested types always have at least as many generic parameters as their enclosing type. Odnoszą się one do parametrów ogólnych w typie otaczającym.These correspond by position to the generic parameters in the enclosing type. Typ ogólny może również zawierać nowe parametry ogólne.The generic type can also include new generic parameters.

Relacja między parametrami typu ogólnego typu zawierającego i jego zagnieżdżonymi typami może być ukryta przez składnię poszczególnych języków.The relationship between the generic type parameters of a containing type and its nested types may be hidden by the syntax of individual languages. W poniższym przykładzie typ ogólny Outer<T> zawiera dwie klasy zagnieżdżone Inner1A i Inner1B<U> .In the following example, a generic type Outer<T> contains two nested classes, Inner1A and Inner1B<U>. Wywołania ToString metody, którą każda klasa dziedziczy z Object.ToString , pokazują, że każda klasa zagnieżdżona zawiera parametry typu klasy zawierającej.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]

Nazwy typów ogólnych są zakodowane w postaci nazwy ` n, gdzie name jest nazwą typu, ` jest literałem znaku, a n to liczba parametrów zadeklarowanych w typie, lub dla zagnieżdżonych typów ogólnych, liczba nowo wprowadzonych parametrów typu.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. To kodowanie nazw typów ogólnych jest szczególnie przydatne dla deweloperów korzystających z odbicia w celu uzyskania dostępu do typów ogólnych z aspektami CLS w bibliotece.This encoding of generic type names is primarily of interest to developers who use reflection to access CLS-complaint generic types in a library.

Jeśli ograniczenia są stosowane do typu generycznego, wszystkie typy używane jako ograniczenia muszą również być zgodne ze specyfikacją CLS.If constraints are applied to a generic type, any types used as constraints must also be CLS-compliant. W poniższym przykładzie zdefiniowano klasę o nazwie BaseClass , która jest niezgodna ze specyfikacją CLS, i klasę generyczną o nazwie, BaseCollection której parametr typu musi pochodzić od 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. Ale ponieważ BaseClass nie jest zgodny ze specyfikacją CLS, kompilator emituje ostrzeżenie.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)
'                                        ~~~~~~~~~

Jeśli typ ogólny pochodzi od generycznego typu podstawowego, musi ponownie zadeklarować wszelkie ograniczenia, aby można było zagwarantować, że ograniczenia dotyczące typu podstawowego również są spełnione.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. W poniższym przykładzie zdefiniowano Number<T> , który może reprezentować dowolny typ liczbowy.The following example defines a Number<T> that can represent any numeric type. Definiuje również FloatingPoint<T> klasę, która reprezentuje wartość zmiennoprzecinkową.It also defines a FloatingPoint<T> class that represents a floating point value. Jednak kod źródłowy nie zostanie skompilowany, ponieważ nie ma zastosowania ograniczenia Number<T> (to T musi być typem wartości) 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)
'                                                          ~

Przykład zostanie skompilowany pomyślnie, jeśli ograniczenie zostanie dodane do FloatingPoint<T> klasy.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

Common Language Specification nakładają się na model tworzenia wystąpień dla zagnieżdżonych typów i chronionych elementów członkowskich.The Common Language Specification imposes a conservative per-instantiation model for nested types and protected members. Otwarte typy ogólne nie mogą ujawniać pól ani członków z podpisami zawierającymi określone wystąpienie zagnieżdżonego, chronionego typu ogólnego.Open generic types cannot expose fields or members with signatures that contain a specific instantiation of a nested, protected generic type. Typy nieogólne, które zwiększają wystąpienie określonego wystąpienia generycznej klasy podstawowej lub interfejsu, nie mogą ujawniać pól ani elementów członkowskich z podpisami zawierającymi różne wystąpienia zagnieżdżonego, chronionego typu ogólnego.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.

Poniższy przykład definiuje typ ogólny, C1<T> (lub C1(Of T) w Visual Basic) i chronioną klasę C1<T>.N (lub C1(Of T).N w Visual Basic).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>ma dwie metody M1 i M2 .C1<T> has two methods, M1 and M2. Jednakże M1 nie jest zgodny ze specyfikacją CLS, ponieważ próbuje zwrócić C1<int>.N obiekt (lub C1(Of Integer).N ) z C1 <T> (lub C1(Of T) ).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)). Druga klasa, C2 ,, pochodzi od C1<long> (lub C1(Of Long) ).A second class, C2, is derived from C1<long> (or C1(Of Long)). Ma dwie metody M3 i M4 .It has two methods, M3 and M4. M3nie jest zgodne ze specyfikacją CLS, ponieważ próbuje zwrócić C1<int>.N obiekt (lub C1(Of Integer).N ) z podklasy C1<long> .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>. Należy zauważyć, że kompilatory języka mogą być jeszcze bardziej restrykcyjne.Note that language compilers can be even more restrictive. W tym przykładzie Visual Basic wyświetla błąd podczas próby skompilowania 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)  
'                             ~~~~~~~~~~~~~

KonstruktoryConstructors

Konstruktory w klasach i strukturach zgodnych ze specyfikacją CLS muszą być zgodne z następującymi regułami:Constructors in CLS-compliant classes and structures must follow these rules:

  • Konstruktor klasy pochodnej musi wywoływać konstruktora wystąpienia swojej klasy bazowej przed uzyskaniem dostępu do danych dziedziczonego wystąpienia.A constructor of a derived class must call the instance constructor of its base class before it accesses inherited instance data. To wymaganie wynika z faktu, że konstruktory klasy bazowej nie są dziedziczone przez ich klasy pochodne.This requirement is due to the fact that base class constructors are not inherited by their derived classes. Ta zasada nie ma zastosowania do struktur, które nie obsługują bezpośredniego dziedziczenia.This rule does not apply to structures, which do not support direct inheritance.

    Zazwyczaj kompilatory wymuszają tę regułę niezależnie od zgodności ze specyfikacją CLS, jak pokazano w poniższym przykładzie.Typically, compilers enforce this rule independently of CLS compliance, as the following example shows. Tworzy Doctor klasę, która jest pochodną Person klasy, ale Doctor nie wywołuje Person konstruktora klasy w celu zainicjowania pól dziedziczonego wystąpienia.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()
    '                  ~~~
    
  • Konstruktor obiektów nie może zostać wywołany z wyjątkiem tworzenia obiektu.An object constructor cannot be called except to create an object. Ponadto nie można dwukrotnie zainicjować obiektu.In addition, an object cannot be initialized twice. Oznacza to na przykład, że Object.MemberwiseClone metody deserializacji, takie jak BinaryFormatter.Deserialize nie mogą wywoływać konstruktorów.For example, this means that Object.MemberwiseClone and deserialization methods such as BinaryFormatter.Deserialize must not call constructors.

WłaściwościProperties

Właściwości typów zgodnych ze specyfikacją CLS muszą być zgodne z następującymi regułami:Properties in CLS-compliant types must follow these rules:

  • Właściwość musi mieć metody ustawiającej, pobierającej lub obu.A property must have a setter, a getter, or both. W zestawie są one implementowane jako metody specjalne, co oznacza, że będą wyświetlane jako oddzielne metody (metoda pobierająca nosi nazwę get_ PropertyName , a Metoda ustawiająca to set_ PropertyName) oznaczona jako SpecialName w metadanych zestawu.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. Kompilatory C# i Visual Basic wymuszają tę regułę automatycznie bez konieczności stosowania CLSCompliantAttribute atrybutu.The C# and Visual Basic compilers enforce this rule automatically without the need to apply the CLSCompliantAttribute attribute.

  • Typ właściwości jest typem zwracanym metody pobierającej właściwości i ostatnim argumentem metody ustawiającej.A property's type is the return type of the property getter and the last argument of the setter. Te typy muszą być zgodne ze specyfikacją CLS, a argumenty nie mogą być przypisywane do właściwości przez odwołanie (oznacza to, że nie mogą być wskaźnikami zarządzanymi).These types must be CLS compliant, and arguments cannot be assigned to the property by reference (that is, they cannot be managed pointers).

  • Jeśli właściwość ma zarówno metodę pobierającą, jak i setter, muszą jednocześnie być wirtualne, zarówno statyczne, jak i oba wystąpienia.If a property has both a getter and a setter, they must both be virtual, both static, or both instance. Kompilatory C# i Visual Basic automatycznie wymuszają tę regułę za pomocą składni definicji właściwości.The C# and Visual Basic compilers automatically enforce this rule through their property definition syntax.

ZdarzeniaEvents

Zdarzenie jest definiowane przy użyciu jego nazwy i typu.An event is defined by its name and its type. Typ zdarzenia jest delegatem, który jest używany do wskazania zdarzenia.The event type is a delegate that is used to indicate the event. Na przykład AppDomain.AssemblyResolve zdarzenie jest typu ResolveEventHandler .For example, the AppDomain.AssemblyResolve event is of type ResolveEventHandler. Oprócz samego zdarzenia trzy metody z nazwami na podstawie nazwy zdarzenia dostarczają implementację zdarzenia i są oznaczone jako SpecialName w metadanych zestawu: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:

  • Metoda dodawania obsługi zdarzeń o nazwie add_ EventName.A method for adding an event handler, named add_EventName. Na przykład Metoda subskrypcji zdarzeń dla AppDomain.AssemblyResolve zdarzenia ma nazwę add_AssemblyResolve .For example, the event subscription method for the AppDomain.AssemblyResolve event is named add_AssemblyResolve.

  • Metoda usuwania programu obsługi zdarzeń o nazwie remove_ EventName.A method for removing an event handler, named remove_EventName. Na przykład metoda usuwania dla AppDomain.AssemblyResolve zdarzenia ma nazwę remove_AssemblyResolve .For example, the removal method for the AppDomain.AssemblyResolve event is named remove_AssemblyResolve.

  • Metoda wskazująca, że zdarzenie wystąpiło o nazwie raise_ EventName.A method for indicating that the event has occurred, named raise_EventName.

Uwaga

Większość reguł Common Language Specification dotyczących zdarzeń jest implementowanych przez kompilatory języka i są przezroczyste dla deweloperów składników.Most of the Common Language Specification's rules regarding events are implemented by language compilers and are transparent to component developers.

Metody dodawania, usuwania i wywoływania zdarzenia muszą mieć taki sam dostęp.The methods for adding, removing, and raising the event must have the same accessibility. Muszą one również być statyczne, wystąpienia lub wirtualne.They must also all be static, instance, or virtual. Metody dodawania i usuwania zdarzenia mają jeden parametr, którego typem jest typ delegata zdarzenia.The methods for adding and removing an event have one parameter whose type is the event delegate type. Metody Add i Remove muszą być obecne lub być nieobecne.The add and remove methods must both be present or both be absent.

W poniższym przykładzie zdefiniowano klasę zgodną ze specyfikacją CLS o nazwie Temperature , która wywołuje TemperatureChanged zdarzenie, jeśli zmiana temperatury między dwoma odczytami jest równa lub przekracza wartość progową.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. TemperatureKlasa jawnie definiuje metodę, raise_TemperatureChanged Aby można było wybiórczo wykonywać procedury obsługi zdarzeń.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

PrzeciążeniaOverloads

Common Language Specification nakładają następujące wymagania dotyczące przeciążonych elementów członkowskich:The Common Language Specification imposes the following requirements on overloaded members:

  • Elementy członkowskie mogą być przeciążone na podstawie liczby parametrów i typu każdego parametru.Members can be overloaded based on the number of parameters and the type of any parameter. Konwencja wywoływania, zwracany typ, Modyfikatory niestandardowe stosowane do metody lub jej parametru oraz czy parametry są przesyłane przez wartość lub przez odwołanie nie są brane pod uwagę podczas różnicowania przeciążeń.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. Aby zapoznać się z przykładem, zobacz kod wymagający, aby nazwy muszą być unikatowe w zakresie w sekcji konwencji nazewnictwa .For an example, see the code for the requirement that names must be unique within a scope in the Naming conventions section.

  • Tylko właściwości i metody mogą być przeciążone.Only properties and methods can be overloaded. Pola i zdarzenia nie mogą być przeciążone.Fields and events cannot be overloaded.

  • Metody generyczne mogą być przeciążone na podstawie liczby parametrów ogólnych.Generic methods can be overloaded based on the number of their generic parameters.

Uwaga

op_ExplicitOperatory i op_Implicit są wyjątkami od reguły, która zwraca wartość nie jest uważana za część sygnatury metody w celu rozpoznania przeciążenia.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. Te dwa operatory mogą być przeciążone na podstawie zarówno ich parametrów, jak i ich wartości zwracanej.These two operators can be overloaded based on both their parameters and their return value.

WyjątkiExceptions

Obiekty wyjątków muszą pochodzić od System.Exception lub z innego typu pochodnego od System.Exception .Exception objects must derive from System.Exception or from another type derived from System.Exception. Poniższy przykład ilustruje błąd kompilatora, który powstaje, gdy Klasa niestandardowa o nazwie ErrorClass jest używana do obsługi wyjątków.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
'             ~~~~~~~~~~~~~~

Aby naprawić ten błąd, ErrorClass Klasa musi dziedziczyć po elemencie System.Exception .To correct this error, the ErrorClass class must inherit from System.Exception. Ponadto Message Właściwość musi być zastąpiona.In addition, the Message property must be overridden. Poniższy przykład koryguje te błędy, aby zdefiniować ErrorClass klasę, która jest zgodna ze specyfikacją CLS.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

AtrybutyAttributes

Zestawy platformy In.NET Framework, atrybuty niestandardowe oferują rozszerzalny mechanizm do przechowywania atrybutów niestandardowych i pobierania metadanych dotyczących obiektów programistycznych, takich jak zestawy, typy, elementy członkowskie i parametry metody.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. Atrybuty niestandardowe muszą pochodzić od System.Attribute lub z typu pochodnego od elementu System.Attribute .Custom attributes must derive from System.Attribute or from a type derived from System.Attribute.

Poniższy przykład narusza tę regułę.The following example violates this rule. Definiuje NumericAttribute klasę, która nie pochodzi od System.Attribute .It defines a NumericAttribute class that does not derive from System.Attribute. Należy zauważyć, że błąd kompilatora występuje tylko wtedy, gdy jest stosowany atrybut niezgodny ze specyfikacją CLS, nie gdy Klasa jest zdefiniowana.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
'     ~~~~~~~~~~~~~

Konstruktor lub właściwości atrybutu zgodnego ze specyfikacją CLS mogą uwidaczniać tylko następujące typy:The constructor or the properties of a CLS-compliant attribute can expose only the following types:

W poniższym przykładzie zdefiniowano DescriptionAttribute klasę, która pochodzi od Attribute .The following example defines a DescriptionAttribute class that derives from Attribute. Konstruktor klasy ma parametr typu Descriptor , więc Klasa nie jest zgodna ze specyfikacją CLS.The class constructor has a parameter of type Descriptor, so the class is not CLS-compliant. Należy zauważyć, że kompilator języka C# emituje ostrzeżenie, ale kompiluje się pomyślnie, natomiast kompilator Visual Basic emituje nie ostrzeżenia ani błędy.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

Atrybut CLSCompliantAttributeThe CLSCompliantAttribute attribute

Ten CLSCompliantAttribute atrybut służy do wskazywania, czy element programu jest zgodny z Common Language Specification.The CLSCompliantAttribute attribute is used to indicate whether a program element complies with the Common Language Specification. CLSCompliantAttribute(Boolean)Konstruktor zawiera jeden wymagany parametr, isCompliant który wskazuje, czy element programu jest zgodny ze specyfikacją CLS.The CLSCompliantAttribute(Boolean) constructor includes a single required parameter, isCompliant, that indicates whether the program element is CLS-compliant.

W czasie kompilacji kompilator wykrywa niezgodne elementy, które są zgodne ze specyfikacją CLS, i emituje ostrzeżenie.At compile time, the compiler detects non-compliant elements that are presumed to be CLS-compliant and emits a warning. Kompilator nie emituje ostrzeżeń dla typów lub elementów członkowskich, które są jawnie zadeklarowane jako niezgodne.The compiler does not emit warnings for types or members that are explicitly declared to be non-compliant.

Deweloperzy składników mogą używać CLSCompliantAttribute atrybutu na dwa sposoby:Component developers can use the CLSCompliantAttribute attribute in two ways:

  • Do definiowania części interfejsu publicznego uwidocznionych przez składnik, który jest zgodny ze specyfikacją CLS, i części, które nie są zgodne ze specyfikacją 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. Gdy atrybut jest używany do oznaczania określonych elementów programu jako zgodnych ze specyfikacją CLS, jego użycie gwarantuje, że te elementy są dostępne we wszystkich językach i narzędziach przeznaczonych dla .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.

  • Aby zapewnić, że interfejs publiczny biblioteki składników uwidacznia tylko elementy programu, które są zgodne ze specyfikacją CLS.To ensure that the component library's public interface exposes only program elements that are CLS-compliant. Jeśli elementy nie są zgodne ze specyfikacją CLS, kompilatory zwykle wygenerują ostrzeżenie.If elements are not CLS-compliant, compilers will generally issue a warning.

Ostrzeżenie

W niektórych przypadkach kompilatory języka wymuszają reguły zgodne ze specyfikacją CLS niezależnie od tego, czy CLSCompliantAttribute atrybut jest używany.In some cases, language compilers enforce CLS-compliant rules regardless of whether the CLSCompliantAttribute attribute is used. Na przykład definiowanie statycznego elementu członkowskiego w interfejsie narusza regułę CLS.For example, defining a static member in an interface violates a CLS rule. W związku z tym, jeśli zdefiniujesz static (w języku c#) lub Shared (w Visual Basic) członek w interfejsie, w kompilatorach C# i Visual Basic zostanie wyświetlony komunikat o błędzie i kompilacja aplikacji nie powiedzie się.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.

CLSCompliantAttributeAtrybut jest oznaczony AttributeUsageAttribute atrybutem, który ma wartość AttributeTargets.All .The CLSCompliantAttribute attribute is marked with an AttributeUsageAttribute attribute that has a value of AttributeTargets.All. Ta wartość umożliwia zastosowanie CLSCompliantAttribute atrybutu do dowolnego elementu programu, w tym zestawów, modułów, typów (klasy, struktury, wyliczenia, interfejsy i delegatów), elementów członkowskich typu (konstruktorów, metod, właściwości, pól i zdarzeń), parametrów, parametrów ogólnych i zwracanych wartości.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. Jednakże, w przypadku, należy zastosować atrybut tylko do zestawów, typów i elementów członkowskich typu.However, in practice, you should apply the attribute only to assemblies, types, and type members. W przeciwnym razie kompilatory ignorują atrybut i kontynuuje generowanie ostrzeżeń kompilatora zawsze wtedy, gdy napotkają niezgodny parametr, parametr ogólny lub wartość zwracaną w interfejsie publicznym biblioteki.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.

Wartość CLSCompliantAttribute atrybutu jest dziedziczona przez zawarte elementy programu.The value of the CLSCompliantAttribute attribute is inherited by contained program elements. Na przykład, jeśli zestaw jest oznaczony jako zgodny ze specyfikacją CLS, jego typy są również zgodne ze specyfikacją CLS.For example, if an assembly is marked as CLS-compliant, its types are also CLS-compliant. Jeśli typ jest oznaczony jako zgodny ze specyfikacją CLS, jego zagnieżdżone typy i elementy członkowskie są również zgodne ze specyfikacją CLS.If a type is marked as CLS-compliant, its nested types and members are also CLS-compliant.

Dziedziczonej zgodności można jawnie zastępować przez zastosowanie CLSCompliantAttribute atrybutu do zawartego elementu programu.You can explicitly override the inherited compliance by applying the CLSCompliantAttribute attribute to a contained program element. Na przykład można użyć CLSCompliantAttribute atrybutu z isCompliant wartością false w celu zdefiniowania niezgodnego typu w zgodnym zestawie i można użyć atrybutu z isCompliant wartością true w celu zdefiniowania zgodnego typu w niezgodnym zestawie.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. Istnieje również możliwość zdefiniowania niezgodnych elementów członkowskich w typie zgodnym.You can also define non-compliant members in a compliant type. Niezgodny typ nie może jednak mieć zgodnych elementów członkowskich, dlatego nie można użyć atrybutu z wartością, isCompliant true Aby zastąpić dziedziczenie z niezgodnego typu.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.

Podczas tworzenia składników należy zawsze używać CLSCompliantAttribute atrybutu, aby wskazać, czy zestaw, jego typy i jego elementy członkowskie są zgodne ze specyfikacją 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.

Aby utworzyć składniki zgodne ze specyfikacją CLS:To create CLS-compliant components:

  1. Użyj, CLSCompliantAttribute Aby oznaczyć zestaw jako zgodny ze specyfikacją CLS.Use the CLSCompliantAttribute to mark you assembly as CLS-compliant.

  2. Oznacz wszystkie publicznie uwidocznione typy w zestawie, które nie są zgodne ze specyfikacją CLS jako niezgodne.Mark any publicly exposed types in the assembly that are not CLS-compliant as non-compliant.

  3. Oznacz wszystkie publicznie uwidocznionych członków w typach zgodnych ze specyfikacją CLS jako niezgodne.Mark any publicly exposed members in CLS-compliant types as non-compliant.

  4. Podaj alternatywę zgodną ze specyfikacją CLS dla członków niezgodnych ze specyfikacją CLS.Provide a CLS-compliant alternative for non-CLS-compliant members.

Jeśli wszystkie niezgodne typy i elementy członkowskie zostały oznaczone pomyślnie, kompilator nie powinien emitować ostrzeżeń o braku zgodności.If you've successfully marked all your non-compliant types and members, your compiler should not emit any non-compliance warnings. Należy jednak wskazać, które elementy członkowskie nie są zgodne ze specyfikacją CLS, i wyświetlić ich alternatywy zgodne ze specyfikacją CLS w dokumentacji produktu.However, you should indicate which members are not CLS-compliant and list their CLS-compliant alternatives in your product documentation.

Poniższy przykład używa CLSCompliantAttribute atrybutu w celu zdefiniowania zestawu zgodnego ze specyfikacją CLS i typu, CharacterUtilities , który ma dwie składowe niezgodne ze specyfikacją CLS.The following example uses the CLSCompliantAttribute attribute to define a CLS-compliant assembly and a type, CharacterUtilities, that has two non-CLS-compliant members. Ponieważ oba elementy członkowskie są oznaczone CLSCompliant(false) atrybutem, kompilator nie generuje ostrzeżeń.Because both members are tagged with the CLSCompliant(false) attribute, the compiler produces no warnings. Klasa zawiera również alternatywę zgodną ze specyfikacją CLS dla obu tych metod.The class also provides a CLS-compliant alternative for both methods. Zwykle należy dodać dwa przeciążenia do ToUTF16 metody, aby zapewnić alternatywy zgodne ze specyfikacją CLS.Ordinarily, we would just add two overloads to the ToUTF16 method to provide CLS-compliant alternatives. Jednak ponieważ metody nie mogą być przeciążone w oparciu o wartość zwracaną, nazwy metod zgodnych ze specyfikacją CLS różnią się od nazw metod niezgodnych.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

Jeśli tworzysz aplikację, a nie bibliotekę (czyli jeśli nie ujawniasz typów lub elementów członkowskich, które mogą być używane przez innych deweloperów aplikacji), zgodność ze specyfikacją CLS elementów programu, których używa aplikacja, jest interesująca tylko wtedy, gdy język ich nie obsługuje.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. W takim przypadku kompilator języka wygeneruje błąd podczas próby użycia elementu niezgodnego ze specyfikacją CLS.In that case, your language compiler will generate an error when you try to use a non-CLS-compliant element.

Współdziałanie między językamiCross-Language Interoperability

Niezależność od języka ma wiele możliwych znaczenia.Language independence has a number of possible meanings. Jednym z nich, który jest omawiany w zależności od języka artykułu i składników niezależnych od języka, obejmuje bezproblemowe zużywanie typów pisanych w jednym języku z aplikacji w innym języku.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. Drugie znaczenie, które jest fokusem tego artykułu, obejmuje łączenie kodu pisanego w wielu językach w jeden zestaw .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.

Poniższy przykład ilustruje współdziałanie między językami przez utworzenie biblioteki klas o nazwie Utilities. dll, która zawiera dwie klasy, NumericLib i StringLib .The following example illustrates cross-language interoperability by creating a class library named Utilities.dll that includes two classes, NumericLib and StringLib. NumericLibKlasa jest zapisywana w języku C#, a StringLib Klasa jest zapisywana w Visual Basic.The NumericLib class is written in C#, and the StringLib class is written in Visual Basic. Oto kod źródłowy dla StringUtil. vb, który zawiera pojedynczy element członkowski, ToTitleCase w swojej StringLib klasie.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

Oto kod źródłowy dla NumberUtil.cs, który definiuje NumericLib klasę, która ma dwa elementy członkowskie, IsEven i 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;
   }
}

Aby spakować dwie klasy w jednym zestawie, należy skompilować je do modułów.To package the two classes in a single assembly, you must compile them into modules. Aby skompilować plik kodu źródłowego Visual Basic do modułu, użyj tego polecenia:To compile the Visual Basic source code file into a module, use this command:

vbc /t:module StringUtil.vb

Aby uzyskać więcej informacji na temat składni wiersza polecenia kompilatora Visual Basic, zobacz Kompilowanie z poziomu wiersza polecenia.For more information about the command-line syntax of the Visual Basic compiler, see Building from the Command Line.

Aby skompilować plik kodu źródłowego C# do modułu, użyj tego polecenia:To compile the C# source code file into a module, use this command:

csc /t:module NumberUtil.cs

Aby uzyskać więcej informacji na temat składni wiersza polecenia kompilatora języka C#, zobacz Kompilowanie wiersza polecenia przy użyciu pliku CSC. exe.For more information about the command-line syntax of the C# compiler, see Command-line Building With csc.exe.

Następnie użyj opcji konsolidatora , aby skompilować dwa moduły do zestawu:You then use the Linker options to compile the two modules into an assembly:

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

Poniższy przykład wywołuje NumericLib.NearZero StringLib.ToTitleCase metody i.The following example then calls the NumericLib.NearZero and StringLib.ToTitleCase methods. Należy zauważyć, że zarówno kod Visual Basic, jak i kod w języku C#, mogą uzyskać dostęp do metod w obu klasach.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

Aby skompilować kod Visual Basic, użyj tego polecenia:To compile the Visual Basic code, use this command:

vbc example.vb /r:UtilityLib.dll

Aby skompilować przy użyciu języka C#, Zmień nazwę kompilatora z VBC na CSCi Zmień rozszerzenie pliku z. vb na. 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

Zobacz teżSee also