Система общих типов CTSCommon Type System

Система общих типов CTS определяет способ объявления, использования и управления типами в среде CLR, а также является важной составной частью поддержки межъязыковой интеграции в среде выполнения.The common type system defines how types are declared, used, and managed in the common language runtime, and is also an important part of the runtime's support for cross-language integration. Система общих типов выполняет следующие функции.The common type system performs the following functions:

  • Формирует инфраструктуру, которая позволяет обеспечивать межъязыковую интеграцию, безопасность типов и высокопроизводительное выполнение кода.Establishes a framework that helps enable cross-language integration, type safety, and high-performance code execution.

  • Предоставляет объектно-ориентированную модель, поддерживающую полную реализацию многих языков программирования.Provides an object-oriented model that supports the complete implementation of many programming languages.

  • Определяет правила, которых необходимо придерживаться в языке. Эти правила помогают обеспечить взаимодействие объектов, написанных на разных языках.Defines rules that languages must follow, which helps ensure that objects written in different languages can interact with each other.

  • Предоставляет библиотеку, которая содержит типы-примитивы (например, Boolean, Byte, Char, Int32 и UInt64), используемые в разработке приложений.Provides a library that contains the primitive data types (such as Boolean, Byte, Char, Int32, and UInt64) used in application development.

В этом разделе содержатся следующие подразделы.This topic contains the following sections:

Типы в .NETTypes in .NET

Все типы на платформе .NET делятся на типы значений и ссылочные типы.All types in .NET are either value types or reference types.

Типы значений — это типы данных, объекты которых представлены фактическим значением объекта.Value types are data types whose objects are represented by the object's actual value. Если экземпляр типа значения присваивается переменной, то эта переменная получает новую копию значения.If an instance of a value type is assigned to a variable, that variable is given a fresh copy of the value.

Ссылочные типы — это типы данных, объекты которых представлены ссылкой (аналогичной указателю) на фактическое значение объекта.Reference types are data types whose objects are represented by a reference (similar to a pointer) to the object's actual value. Если экземпляр ссылочного типа присваивается переменной, то эта переменная будет ссылаться (указывать) на исходное значение.If a reference type is assigned to a variable, that variable references (points to) the original value. Копирования при этом не происходит.No copy is made.

Система общих типов CTS на платформе .NET поддерживает следующие пять категорий типов:The common type system in .NET supports the following five categories of types:

КлассыClasses

Класс — это ссылочный тип, который может быть прямым производным от другого класса и является неявным производным от типа System.Object.A class is a reference type that can be derived directly from another class and that is derived implicitly from System.Object. В классе определяются операции, которые объект (являющийся экземпляром класса) может выполнять (методы, события или свойства), и данные, которые объект содержит (поля).The class defines the operations that an object (which is an instance of the class) can perform (methods, events, or properties) and the data that the object contains (fields). Обычно класс включает и определение, и реализацию (в отличие, например, от интерфейса, который содержит только определение без реализации), однако один или несколько членов класса могут не иметь реализации.Although a class generally includes both definition and implementation (unlike interfaces, for example, which contain only definition without implementation), it can have one or more members that have no implementation.

В приведенной ниже таблице описываются некоторые характеристики, которыми может обладать класс.The following table describes some of the characteristics that a class may have. Каждый язык, поддерживающий среду выполнения, позволяет указать на наличие у класса или члена класса одной или нескольких из этих характеристик.Each language that supports the runtime provides a way to indicate that a class or class member has one or more of these characteristics. Вместе с тем отдельные языки программирования, ориентированные на платформу .NET, могут не поддерживать некоторые из этих характеристик.However, individual programming languages that target .NET may not make all these characteristics available.

ХарактеристикаCharacteristic ОписаниеDescription
sealedsealed Указывает, что наследование от данного класса не допускается.Specifies that another class cannot be derived from this type.
реализуетimplements Показывает, что в классе используется один или несколько интерфейсов за счет предоставления реализаций их членов.Indicates that the class uses one or more interfaces by providing implementations of interface members.
abstractabstract Указывает, что создавать экземпляры этого класса нельзя.Indicates that the class cannot be instantiated. Чтобы его использовать, необходимо создать из данного класса производный класс.To use it, you must derive another class from it.
наследуетinherits Показывает, что экземпляры класса можно использовать везде, где задан базовый класс.Indicates that instances of the class can be used anywhere the base class is specified. Производный класс, который наследует от базового, может использовать реализацию любых открытых членов, предоставляемых базовым классом, либо переопределить реализацию этих открытых членов собственной их реализацией.A derived class that inherits from a base class can use the implementation of any public members provided by the base class, or the derived class can override the implementation of the public members with its own implementation.
exported или not exportedexported or not exported Показывает, виден ли класс за пределами сборки, в которой он определен.Indicates whether a class is visible outside the assembly in which it is defined. Эта характеристика применима только к классам верхнего уровня, но не к вложенным классам.This characteristic applies only to top-level classes and not to nested classes.

Примечание

Класс может также быть вложен в родительский класс или родительскую структуру.A class can also be nested in a parent class or structure. Вложенные классы также имеют характеристики членов.Nested classes also have member characteristics. Дополнительные сведения см. в разделе Вложенные типы.For more information, see Nested Types.

Члены классов, не имеющие реализации, являются абстрактными.Class members that have no implementation are abstract members. Класс, содержащий несколько абстрактных членов, сам является абстрактным. Новые экземпляры этого класса создать нельзя.A class that has one or more abstract members is itself abstract; new instances of it cannot be created. Некоторые языки, ориентированные на среду выполнения, позволяют пометить класс как абстрактный даже в том случае, если он не содержит ни одного абстрактного члена.Some languages that target the runtime let you mark a class as abstract even if none of its members are abstract. Абстрактный класс можно использовать, когда требуется инкапсулировать базовый набор функциональных возможностей, которые производные классы могут наследовать или переопределять.You can use an abstract class when you want to encapsulate a basic set of functionality that derived classes can inherit or override when appropriate. Классы, не являющиеся абстрактными, называются конкретными классами.Classes that are not abstract are referred to as concrete classes.

Класс может реализовывать любое число интерфейсов, однако он может наследовать только от одного базового класса в дополнение к System.Object, от которого неявно наследуют все классы.A class can implement any number of interfaces, but it can inherit from only one base class in addition to System.Object, from which all classes inherit implicitly. Любой класс должен иметь по крайней мере один конструктор, который инициализирует новые экземпляры класса.All classes must have at least one constructor, which initializes new instances of the class. Если конструктор не определен явно, большинство компиляторов автоматически предоставят заданный конструктор без параметров.If you do not explicitly define a constructor, most compilers will automatically provide a parameterless constructor.

СтруктурыStructures

Структура — это тип значения, неявно производный от типа System.ValueType, который, в свою очередь, является производным от типа System.Object.A structure is a value type that derives implicitly from System.ValueType, which in turn is derived from System.Object. Структуры весьма полезны для представления значений с небольшими требованиями к памяти и для передачи параметров по значению в методы со строгой типизацией параметров.A structure is very useful for representing values whose memory requirements are small, and for passing values as by-value parameters to methods that have strongly typed parameters. В .NET все типы-примитивы (Boolean, Byte, Char, DateTime, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32 и UInt64) определяются как структуры.In .NET, all primitive data types (Boolean, Byte, Char, DateTime, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, and UInt64) are defined as structures.

Как и в классах, в структурах определяются и данные (поля структуры), и операции, которые можно выполнять над этими данными (методы структуры).Like classes, structures define both data (the fields of the structure) and the operations that can be performed on that data (the methods of the structure). Это означает, что применительно к структурам можно вызывать методы, в том числе виртуальные методы, определенные в классах System.Object и System.ValueType, а также любые методы, определенные в самом типе значения.This means that you can call methods on structures, including the virtual methods defined on the System.Object and System.ValueType classes, and any methods defined on the value type itself. Другими словами, структуры могут иметь поля, свойства и события, а также статические и нестатические методы.In other words, structures can have fields, properties, and events, as well as static and nonstatic methods. Можно создавать экземпляры структур, передавать их в качестве параметров, хранить их в качестве локальных переменных либо в поле другого типа значения или ссылочного типа.You can create instances of structures, pass them as parameters, store them as local variables, or store them in a field of another value type or reference type. Структуры также могут реализовывать интерфейсы.Structures can also implement interfaces.

Кроме того, типы значений отличаются от классов в ряде других вопросов.Value types also differ from classes in several respects. Во-первых, хотя они неявно наследуют от System.ValueType, они не могут напрямую наследовать ни от какого типа.First, although they implicitly inherit from System.ValueType, they cannot directly inherit from any type. Аналогичным образом, все типы значений являются запечатанными. Это значит, что наследование от них не допускается.Similarly, all value types are sealed, which means that no other type can be derived from them. Им также не требуются конструкторы.They also do not require constructors.

Для каждого типа значения среда CLR предоставляет соответствующий упакованный тип — класс, имеющий то же состояние и поведение, что и тип значения.For each value type, the common language runtime supplies a corresponding boxed type, which is a class that has the same state and behavior as the value type. Экземпляр типа значения упаковывается при передаче в метод, принимающий параметр типа System.Object.An instance of a value type is boxed when it is passed to a method that accepts a parameter of type System.Object. Распаковка (преобразование из экземпляра класса обратно в экземпляр типа значения) производится при возврате управления после вызова метода, принимающего тип значения в качестве параметра по ссылке.It is unboxed (that is, converted from an instance of a class back to an instance of a value type) when control returns from a method call that accepts a value type as a by-reference parameter. В некоторых языках необходимо применение специального синтаксиса, когда требуется упакованный тип; в других упакованный тип используется автоматически, когда он нужен.Some languages require that you use special syntax when the boxed type is required; others automatically use the boxed type when it is needed. При определении типа значений определяется и упакованный, и неупакованный тип.When you define a value type, you are defining both the boxed and the unboxed type.

ПеречисленияEnumerations

Перечисление (enum) — это тип значения, который напрямую наследует от System.Enum и предоставляет альтернативные имена для значений базового типа-примитива.An enumeration (enum) is a value type that inherits directly from System.Enum and that supplies alternate names for the values of an underlying primitive type. Тип перечисления имеет имя, базовый тип, который должен быть одним из встроенных целочисленных знаковых или беззнаковых типов (например, Byte, Int32 или UInt64), а также набор полей.An enumeration type has a name, an underlying type that must be one of the built-in signed or unsigned integer types (such as Byte, Int32, or UInt64), and a set of fields. Поля являются статическими полями литералов, каждое из которых представляет константу.The fields are static literal fields, each of which represents a constant. Одно значение можно присвоить нескольким полям.The same value can be assigned to multiple fields. В этом случае необходимо пометить одно из значений как первичное значение перечисления для отражения и преобразования строк.When this occurs, you must mark one of the values as the primary enumeration value for reflection and string conversion.

Значение базового типа можно присвоить перечислению и наоборот (среда выполнения не требует приведения типов).You can assign a value of the underlying type to an enumeration and vice versa (no cast is required by the runtime). Можно создавать экземпляры перечислений и вызвать методы System.Enum, а также любые методы, определенные в базовом типе перечисления.You can create an instance of an enumeration and call the methods of System.Enum, as well as any methods defined on the enumeration's underlying type. При этом в некоторых языках передача перечисления в виде параметра может не допускаться, если требуется передать экземпляр базового типа (или наоборот).However, some languages might not let you pass an enumeration as a parameter when an instance of the underlying type is required (or vice versa).

К перечислениям применяются следующие дополнительные ограничения.The following additional restrictions apply to enumerations:

  • В них нельзя определять собственные методы.They cannot define their own methods.

  • В них нельзя реализовывать интерфейсы.They cannot implement interfaces.

  • В них нельзя определять свойства и события.They cannot define properties or events.

  • Они не могут быть универсальными, если только они становятся таковыми за счет вложения внутрь универсального типа.They cannot be generic, unless they are generic only because they are nested within a generic type. То есть перечисления не могут иметь свои собственные параметры типов.That is, an enumeration cannot have type parameters of its own.

    Примечание

    Вложенные типы (в том числе перечисления), созданные в Visual Basic, C# и C++, содержат параметры всех включающих их универсальных типов и, таким образом, являются универсальными, даже если они не имеют своих собственных параметров типов.Nested types (including enumerations) created with Visual Basic, C#, and C++ include the type parameters of all enclosing generic types, and are therefore generic even if they do not have type parameters of their own. Дополнительные сведения см. в подразделе "Вложенные типы" раздела справки Type.MakeGenericType.For more information, see "Nested Types" in the Type.MakeGenericType reference topic.

Атрибут FlagsAttribute обозначает специальный вид перечисления, называемый битовым полем.The FlagsAttribute attribute denotes a special kind of enumeration called a bit field. Среда выполнения (в отличие от языка программирования) не различает обычные перечисления и битовые поля.The runtime itself does not distinguish between traditional enumerations and bit fields, but your language might do so. Если это отличие обнаружено, для создания неименованных значений в битовых полях можно использовать битовые операторы (в перечислениях их использовать нельзя).When this distinction is made, bitwise operators can be used on bit fields, but not on enumerations, to generate unnamed values. Перечисления обычно используются для списков уникальных элементов, например дней недели, названий стран или областей и т. д.Enumerations are generally used for lists of unique elements, such as days of the week, country or region names, and so on. Битовые поля обычно используются для списков количеств и качеств, которые могут возникать в таких комбинациях, как Red And Big And Fast.Bit fields are generally used for lists of qualities or quantities that might occur in combination, such as Red And Big And Fast.

В следующем примере показан способ использования битовых полей и обычных перечислений.The following example shows how to use both bit fields and traditional enumerations.

using System;
using System.Collections.Generic;

// A traditional enumeration of some root vegetables.
public enum SomeRootVegetables
{
    HorseRadish,
    Radish,
    Turnip
}

// A bit field or flag enumeration of harvesting seasons.
[Flags]
public enum Seasons
{
    None = 0,
    Summer = 1,
    Autumn = 2,
    Winter = 4,
    Spring = 8,
    All = Summer | Autumn | Winter | Spring
}

public class Example
{
   public static void Main()
   {
       // Hash table of when vegetables are available.
       Dictionary<SomeRootVegetables, Seasons> AvailableIn = new Dictionary<SomeRootVegetables, Seasons>();

       AvailableIn[SomeRootVegetables.HorseRadish] = Seasons.All;
       AvailableIn[SomeRootVegetables.Radish] = Seasons.Spring;
       AvailableIn[SomeRootVegetables.Turnip] = Seasons.Spring | 
            Seasons.Autumn;

       // Array of the seasons, using the enumeration.
       Seasons[] theSeasons = new Seasons[] { Seasons.Summer, Seasons.Autumn, 
            Seasons.Winter, Seasons.Spring };

       // Print information of what vegetables are available each season.
       foreach (Seasons season in theSeasons)
       {
          Console.Write(String.Format(
              "The following root vegetables are harvested in {0}:\n", 
              season.ToString("G")));
          foreach (KeyValuePair<SomeRootVegetables, Seasons> item in AvailableIn)
          {
             // A bitwise comparison.
             if (((Seasons)item.Value & season) > 0)
                 Console.Write(String.Format("  {0:G}\n", 
                      (SomeRootVegetables)item.Key));
          }
       }
   }
}
// The example displays the following output:
//    The following root vegetables are harvested in Summer:
//      HorseRadish
//    The following root vegetables are harvested in Autumn:
//      Turnip
//      HorseRadish
//    The following root vegetables are harvested in Winter:
//      HorseRadish
//    The following root vegetables are harvested in Spring:
//      Turnip
//      Radish
//      HorseRadish
Imports System.Collections.Generic

' A traditional enumeration of some root vegetables.
Public Enum SomeRootVegetables
   HorseRadish
   Radish
   Turnip
End Enum 

' A bit field or flag enumeration of harvesting seasons.
<Flags()> Public Enum Seasons
   None = 0
   Summer = 1
   Autumn = 2
   Winter = 4
   Spring = 8
   All = Summer Or Autumn Or Winter Or Spring
End Enum 

' Entry point.
Public Class Example
   Public Shared Sub Main()
      ' Hash table of when vegetables are available.
      Dim AvailableIn As New Dictionary(Of SomeRootVegetables, Seasons)()
        
      AvailableIn(SomeRootVegetables.HorseRadish) = Seasons.All
      AvailableIn(SomeRootVegetables.Radish) = Seasons.Spring
      AvailableIn(SomeRootVegetables.Turnip) = Seasons.Spring Or _
                                               Seasons.Autumn
        
      ' Array of the seasons, using the enumeration.
      Dim theSeasons() As Seasons = {Seasons.Summer, Seasons.Autumn, _
                                     Seasons.Winter, Seasons.Spring}
        
      ' Print information of what vegetables are available each season.
      For Each season As Seasons In theSeasons
         Console.WriteLine(String.Format( _
              "The following root vegetables are harvested in {0}:", _
              season.ToString("G")))
         For Each item As KeyValuePair(Of SomeRootVegetables, Seasons) In AvailableIn
            ' A bitwise comparison.
            If(CType(item.Value, Seasons) And season) > 0 Then
               Console.WriteLine("  " + _
                     CType(item.Key, SomeRootVegetables).ToString("G"))
            End If
         Next
      Next
   End Sub 
End Class 
' The example displays the following output:
'    The following root vegetables are harvested in Summer:
'      HorseRadish
'    The following root vegetables are harvested in Autumn:
'      Turnip
'      HorseRadish
'    The following root vegetables are harvested in Winter:
'      HorseRadish
'    The following root vegetables are harvested in Spring:
'      Turnip
'      Radish
'      HorseRadish

ИнтерфейсыInterfaces

Интерфейс задает контракт, определяющий отношение типа "может" или "имеет".An interface defines a contract that specifies a "can do" relationship or a "has a" relationship. Интерфейсы часто используются для реализации различных функций, например для сравнения и сортировки (интерфейсы IComparable и IComparable<T>), проверки равенства (интерфейс IEquatable<T>) или перечисления элементов коллекции (интерфейсы IEnumerable и IEnumerable<T>).Interfaces are often used to implement functionality, such as comparing and sorting (the IComparable and IComparable<T> interfaces), testing for equality (the IEquatable<T> interface), or enumerating items in a collection (the IEnumerable and IEnumerable<T> interfaces). Интерфейсы могут иметь свойства, методы и события, являющиеся абстрактными членами. Это значит, что хотя в интерфейсе определяются члены и их сигнатуры, за определение функциональности всех членов интерфейса отвечает тип, реализующий данный интерфейс.Interfaces can have properties, methods, and events, all of which are abstract members; that is, although the interface defines the members and their signatures, it leaves it to the type that implements the interface to define the functionality of each interface member. Любой класс или структура, реализующие интерфейс, должны содержать определения абстрактных членов, объявленных в этом интерфейсе.This means that any class or structure that implements an interface must supply definitions for the abstract members declared in the interface. Обязательным условием реализации интерфейса в классе или структуре также может быть реализация одного или нескольких других интерфейсов.An interface can require any implementing class or structure to also implement one or more other interfaces.

К интерфейсам применяются следующие ограничения.The following restrictions apply to interfaces:

  • Интерфейс может быть объявлен с любой доступностью, однако, члены интерфейса всегда должны иметь доступность уровня public.An interface can be declared with any accessibility, but interface members must all have public accessibility.

  • В интерфейсах нельзя определять конструкторы.Interfaces cannot define constructors.

  • В интерфейсах нельзя определять поля.Interfaces cannot define fields.

  • В интерфейсах можно определять только члены экземпляров.Interfaces can define only instance members. Статические члены определять в них нельзя.They cannot define static members.

Поскольку в нескольких интерфейсах могут быть объявлены члены с одной и той же сигнатурой, имеющие разные реализации, любой язык должен предоставлять правила сопоставления реализации с интерфейсом, для которого требуется данный член.Each language must provide rules for mapping an implementation to the interface that requires the member, because more than one interface can declare a member with the same signature, and these members can have separate implementations.

ДелегатыDelegates

Делегаты — это ссылочные типы, аналогичные по назначению указателям на функции в языке C++.Delegates are reference types that serve a purpose similar to that of function pointers in C++. Они применяются в обработчиках событий и функциях обратного вызова в составе платформы .NET.They are used for event handlers and callback functions in .NET. В отличие от указателей функций, делегаты являются безопасными, проверяемыми и типобезопасными.Unlike function pointers, delegates are secure, verifiable, and type safe. Тип делегата может представлять любой метод экземпляра или статический метод, имеющий совместимую сигнатуру.A delegate type can represent any instance method or static method that has a compatible signature.

Если тип параметра делегата является более строгим, чем тип параметра метода, то параметр делегата совместим с соответствующим параметром метода, так как это гарантирует, что аргумент, переданный делегату, может быть безопасно передан методу.A parameter of a delegate is compatible with the corresponding parameter of a method if the type of the delegate parameter is more restrictive than the type of the method parameter, because this guarantees that an argument passed to the delegate can be passed safely to the method.

Аналогичным образом, тип возвращаемого значения делегата совместим с типом возвращаемого значения метода, если тип возвращаемого значения метода является более строгим, чем тип возвращаемого значения делегата, так как это гарантирует, что возвращаемое значение метода может быть безопасно приведено к типу возвращаемого значения делегата.Similarly, the return type of a delegate is compatible with the return type of a method if the return type of the method is more restrictive than the return type of the delegate, because this guarantees that the return value of the method can be cast safely to the return type of the delegate.

Например, делегат с параметром типа IEnumerable и типом возвращаемого значения Object может представлять метод с параметром типа Object и типом возвращаемого значения IEnumerable.For example, a delegate that has a parameter of type IEnumerable and a return type of Object can represent a method that has a parameter of type Object and a return value of type IEnumerable. Дополнительные сведения и примеры с кодом см. в разделе Delegate.CreateDelegate(Type, Object, MethodInfo).For more information and example code, see Delegate.CreateDelegate(Type, Object, MethodInfo).

Делегат называют связанным с методом, который он представляет.A delegate is said to be bound to the method it represents. Помимо привязки к методу, делегат может быть связан с отдельным объектом.In addition to being bound to the method, a delegate can be bound to an object. Этот объект представляет первый параметр метода и передается методу при каждом вызове делегата.The object represents the first parameter of the method, and is passed to the method every time the delegate is invoked. Если это метод экземпляра, то связанный объект передается как неявный параметр this (Me в Visual Basic); если метод является статическим, то объект передается как первый формальный параметр метода, и сигнатура делегата при этом должна соответствовать остальным параметрам.If the method is an instance method, the bound object is passed as the implicit this parameter (Me in Visual Basic); if the method is static, the object is passed as the first formal parameter of the method, and the delegate signature must match the remaining parameters. Дополнительные сведения и примеры с кодом см. в разделе System.Delegate.For more information and example code, see System.Delegate.

Все делегаты наследуются от System.MulticastDelegate, который наследуется от System.Delegate.All delegates inherit from System.MulticastDelegate, which inherits from System.Delegate. Языки C#, Visual Basic и C++ не допускают наследование от этих типов.The C#, Visual Basic, and C++ languages do not allow inheritance from these types. Вместо этого они предоставляют ключевые слова для объявления делегатов.Instead, they provide keywords for declaring delegates.

Поскольку делегаты наследуются от MulticastDelegate, делегат имеет список вызова, представляющий собой список методов, которые представляет делегат и которые выполняются при вызове делегата.Because delegates inherit from MulticastDelegate, a delegate has an invocation list, which is a list of methods that the delegate represents and that are executed when the delegate is invoked. Все методы в списке получают аргументы, предоставляемые при вызове делегата.All methods in the list receive the arguments supplied when the delegate is invoked.

Примечание

Для делегата, имеющего более одного метода в списке вызовов, возвращаемое значение не определяется, даже если у делегата есть возвращаемый тип.The return value is not defined for a delegate that has more than one method in its invocation list, even if the delegate has a return type.

Зачастую, как, например, в случае с методами обратного вызова, делегат представляет только один метод, поэтому единственное действие, которое нужно выполнить, — это создание и вызов делегата.In many cases, such as with callback methods, a delegate represents only one method, and the only actions you have to take are creating the delegate and invoking it.

Для делегатов, представляющих несколько методов, .NET предоставляет в классах делегатов методы Delegate и MulticastDelegate для поддержки таких операций, как добавление методов к списку вызовов делегата (метод Delegate.Combine), удаление метода (метод Delegate.Remove) и получение списка вызовов (метод Delegate.GetInvocationList).For delegates that represent multiple methods, .NET provides methods of the Delegate and MulticastDelegate delegate classes to support operations such as adding a method to a delegate's invocation list (the Delegate.Combine method), removing a method (the Delegate.Remove method), and getting the invocation list (the Delegate.GetInvocationList method).

Примечание

Применение этих методов к делегатам обработчиков событий в C#, C++ и Visual Basic необязательно, так как эти языки предоставляют синтаксис для добавления и удаления обработчиков событий.It is not necessary to use these methods for event-handler delegates in C#, C++, and Visual Basic, because these languages provide syntax for adding and removing event handlers.

Определения типовType Definitions

Определение типа включает следующее:A type definition includes the following:

  • все определенные в типе атрибуты;Any attributes defined on the type.

  • доступность (видимость) типа;The type's accessibility (visibility).

  • имя типа;The type's name.

  • базовый тип данного типа;The type's base type.

  • все интерфейсы, реализованные этим типом;Any interfaces implemented by the type.

  • определения каждого члена типа.Definitions for each of the type's members.

АтрибутыAttributes

Атрибуты предоставляют дополнительные пользовательские метаданные.Attributes provide additional user-defined metadata. Они чаще всего используются для хранения дополнительной информации о типе в его сборке либо для изменения поведения члена типа во время разработки или выполнения.Most commonly, they are used to store additional information about a type in its assembly, or to modify the behavior of a type member in either the design-time or run-time environment.

Сами атрибуты представляют собой классы, производные от System.Attribute.Attributes are themselves classes that inherit from System.Attribute. Любой язык, поддерживающий использование атрибутов, имеет собственный синтаксис для применения атрибутов к элементам языка.Languages that support the use of attributes each have their own syntax for applying attributes to a language element. Атрибуты можно применять почти к любым элементам языка; конкретные элементы, к которым можно применять определенный атрибут, задаются атрибутом AttributeUsageAttribute, примененным к классу этого атрибута.Attributes can be applied to almost any language element; the specific elements to which an attribute can be applied are defined by the AttributeUsageAttribute that is applied to that attribute class.

Доступность типовType Accessibility

Все типы имеют модификатор, который определяет их доступность из других типов.All types have a modifier that governs their accessibility from other types. В следующей таблице описаны виды доступности типов, поддерживаемые в среде выполнения.The following table describes the type accessibilities supported by the runtime.

Специальные возможностиAccessibility ОписаниеDescription
publicpublic Тип доступен во всех сборках.The type is accessible by all assemblies.
сборкаassembly Тип доступен только в пределах своей сборки.The type is accessible only from within its assembly.

Доступность вложенного типа зависит от домена доступности, который определяется объявленным уровнем доступности члена и доменом доступности непосредственно вмещающего его типа.The accessibility of a nested type depends on its accessibility domain, which is determined by both the declared accessibility of the member and the accessibility domain of the immediately containing type. Однако домен доступности вложенного типа не может выходить за границы домена доступности содержащего его типа.However, the accessibility domain of a nested type cannot exceed that of the containing type.

Домен доступности вложенного члена M, объявленного в типе T в рамках программы P, определяется следующим образом (при этом M также может быть типом):The accessibility domain of a nested member M declared in a type T within a program P is defined as follows (noting that M might itself be a type):

  • Если объявленный уровень доступности Mpublic, то домен доступности M совпадает с доменом доступности T.If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.

  • Если объявленный уровень доступности Mprotected internal, то домен доступности M представляет собой пересечение домена доступности T с текстом программы P и текстом программ любого типа, производного от T и объявленного вне P.If the declared accessibility of M is protected internal, the accessibility domain of M is the intersection of the accessibility domain of T with the program text of P and the program text of any type derived from T declared outside P.

  • Если объявленный уровень доступности Mprotected, то домен доступности M представляет собой пересечение домена доступности T с текстом программы T и текстом программы любого типа, производного от T.If the declared accessibility of M is protected, the accessibility domain of M is the intersection of the accessibility domain of T with the program text of T and any type derived from T.

  • Если объявленный уровень доступности Minternal, то домен доступности M представляет собой пересечение домена доступности T с текстом программы P.If the declared accessibility of M is internal, the accessibility domain of M is the intersection of the accessibility domain of T with the program text of P.

  • Если объявленный уровень доступности Mprivate, то домен доступности M совпадает с текстом программы T.If the declared accessibility of M is private, the accessibility domain of M is the program text of T.

Имена типовType Names

Система общих типов накладывает на имена только два следующих ограничения.The common type system imposes only two restrictions on names:

  • Все имена кодируются в виде строк, состоящих из символов Юникода (16-разрядная кодировка).All names are encoded as strings of Unicode (16-bit) characters.

  • Имена не могут иметь внедренное (16-разрядное) значение 0x0000.Names are not permitted to have an embedded (16-bit) value of 0x0000.

Тем не менее в большинстве языков на имена типов налагаются дополнительные ограничения.However, most languages impose additional restrictions on type names. Все сравнения выполняются на побайтовой основе, поэтому в них учитывается регистр, но они не зависят от языкового стандарта.All comparisons are done on a byte-by-byte basis, and are therefore case-sensitive and locale-independent.

Несмотря на то, что тип может ссылаться на типы из других модулей и сборок, он должен полностью определяться в одном модуле платформы .NET.Although a type might reference types from other modules and assemblies, a type must be fully defined within one .NET module. (Тем не менее при поддержке соответствующей возможности в компиляторе он может быть разделен на несколько файлов исходного кода.) Имена типов должны быть уникальными только в пределах пространства имен.(Depending on compiler support, however, it can be divided into multiple source code files.) Type names need be unique only within a namespace. Для полной идентификации типа его имя должно квалифицироваться именем пространства имен, в котором содержится реализация этого типа.To fully identify a type, the type name must be qualified by the namespace that contains the implementation of the type.

Базовые типы и интерфейсыBase Types and Interfaces

Тип может наследовать значения и поведение другого типа.A type can inherit values and behaviors from another type. Система общих типов не разрешает наследование от нескольких базовых типов.The common type system does not allow types to inherit from more than one base type.

Тип может реализовывать любое число интерфейсов.A type can implement any number of interfaces. Для этого он должен реализовать все виртуальные члены этого интерфейса.To implement an interface, a type must implement all the virtual members of that interface. Виртуальный метод может быть реализован с помощью производного типа и может вызываться либо статически, либо динамически.A virtual method can be implemented by a derived type and can be invoked either statically or dynamically.

Члены типовType Members

Среда выполнения позволяет определять члены типа, задающих поведение и состояние типа.The runtime enables you to define members of your type, which specifies the behavior and state of a type. К членам типа относятся:Type members include the following:

ПоляFields

Поле описывает и содержит часть состояния типа.A field describes and contains part of the type's state. Поля могут иметь любой тип, поддерживаемый средой выполнения.Fields can be of any type supported by the runtime. Поля чаще всего имеют уровень доступности private или protected, поэтому они доступны только изнутри самого класса или из производных от него классов.Most commonly, fields are either private or protected, so that they are accessible only from within the class or from a derived class. Если значение поля может быть изменено извне его типа, то для этого обычно используется метод доступа набора свойств.If the value of a field can be modified from outside its type, a property set accessor is typically used. Открытые поля обычно доступны только для чтения и могут относиться к одному из двух типов:Publicly exposed fields are usually read-only and can be of two types:

  • Константы, значение которых задается во время разработки.Constants, whose value is assigned at design time. Они являются статическими членами класса, хотя и не определяются с помощью ключевого слова static (Shared в Visual Basic).These are static members of a class, although they are not defined using the static (Shared in Visual Basic) keyword.

  • Доступные только для чтения переменные, значения которых задаются в конструкторе класса.Read-only variables, whose values can be assigned in the class constructor.

В следующем примере демонстрируются эти два способа использования доступных только для чтения полей.The following example illustrates these two usages of read-only fields.

using System;

public class Constants
{
   public const double Pi = 3.1416;
   public readonly DateTime BirthDate;
   
   public Constants(DateTime birthDate)
   {
      this.BirthDate = birthDate;
   }
}

public class Example
{
   public static void Main()
   {
      Constants con = new Constants(new DateTime(1974, 8, 18));
      Console.Write(Constants.Pi + "\n");
      Console.Write(con.BirthDate.ToString("d") + "\n");
   }
}
// The example displays the following output if run on a system whose current
// culture is en-US:
//    3.1416
//    8/18/1974
Public Class Constants
   Public Const Pi As Double = 3.1416
   Public ReadOnly BirthDate As Date
   
   Public Sub New(birthDate As Date)
      Me.BirthDate = birthDate
   End Sub
End Class

Public Module Example
   Public Sub Main()
      Dim con As New Constants(#8/18/1974#)
      Console.WriteLine(Constants.Pi.ToString())
      Console.WriteLine(con.BirthDate.ToString("d"))
   End Sub
End Module
' The example displays the following output if run on a system whose current
' culture is en-US:
'    3.1416
'    8/18/1974

СвойстваProperties

Свойство задает определенное значение или состояние типа, а также определяет методы получения и установки значения свойства.A property names a value or state of the type and defines methods for getting or setting the property's value. Свойства могут быть простыми типами, коллекциями простых типов, пользовательскими типами или коллекциями пользовательских типов.Properties can be primitive types, collections of primitive types, user-defined types, or collections of user-defined types. Свойства часто используются, чтобы обеспечить независимость общего интерфейса типа от фактической реализации данного типа.Properties are often used to keep the public interface of a type independent from the type's actual representation. Это позволяет представлять с помощью свойств значения, которые не хранятся непосредственно в классе (например, когда свойство возвращает вычисляемое значение), либо выполнять проверку перед присваиванием значений закрытым полям.This enables properties to reflect values that are not directly stored in the class (for example, when a property returns a computed value) or to perform validation before values are assigned to private fields. В следующем примере демонстрируется второй вариант.The following example illustrates the latter pattern.

using System;

public class Person
{
   private int m_Age;
   
   public int Age
   { 
      get { return m_Age; }
      set {
         if (value < 0 || value > 125)
         {
            throw new ArgumentOutOfRangeException("The value of the Age property must be between 0 and 125.");
         }
         else
         {
            m_Age = value;
         }         
      }
   }
}
Public Class Person
   Private m_Age As Integer
   
   Public Property Age As Integer
      Get
         Return m_Age
      End Get
      Set
         If value < 0 Or value > 125 Then
            Throw New ArgumentOutOfRangeException("The value of the Age property must be between 0 and 125.")
         Else
            m_Age = value
         End If
      End Set
   End Property
End Class

MSIL-код типа, который содержит свойство, доступное для чтения, наряду с самим свойством включает метод get_имя_свойства. MSIL-код типа, который содержит свойство, доступное для чтения, наряду с самим свойством включает метод set_имя_свойства.In addition to including the property itself, the Microsoft intermediate language (MSIL) for a type that contains a readable property includes a get_propertyname method, and the MSIL for a type that contains a writable property includes a set_propertyname method.

МетодыMethods

Метод описывает операции, доступные в определенном типе.A method describes operations that are available on the type. Сигнатура метода указывает допустимые типы всех его параметров и возвращаемого значения.A method's signature specifies the allowable types of all its parameters and of its return value.

Хотя большинство методов определяют точное число параметров, необходимых для вызовов метода, некоторые методы поддерживают переменное число параметров.Although most methods define the precise number of parameters required for method calls, some methods support a variable number of parameters. Конечный объявленный параметр этих методов помечается атрибутом ParamArrayAttribute.The final declared parameter of these methods is marked with the ParamArrayAttribute attribute. Компиляторы языка обычно предоставляют ключевое слово, такое как params в C# и ParamArray в Visual Basic, которое исключает необходимость явного использования ParamArrayAttribute.Language compilers typically provide a keyword, such as params in C# and ParamArray in Visual Basic, that makes explicit use of ParamArrayAttribute unnecessary.

КонструкторыConstructors

Конструктор — это специальный метод, который служит для создания новых экземпляров класса или структуры.A constructor is a special kind of method that creates new instances of a class or structure. Как и любой другой метод, конструктор может иметь параметры, однако у конструкторов отсутствует возвращаемое значение (они возвращают void).Like any other method, a constructor can include parameters; however, constructors have no return value (that is, they return void).

Если исходный код класса не содержит явного определения конструктора, то компилятор включает заданный конструктор без параметров.If the source code for a class does not explicitly define a constructor, the compiler includes a parameterless constructor. Однако если исходный код класса определяет только параметризованные конструкторы, компиляторы Visual Basic и C# не создают конструктор без параметров.However, if the source code for a class defines only parameterized constructors, the Visual Basic and C# compilers do not generate a parameterless constructor.

Если исходный код для структуры определяет конструкторы, они должны быть параметризованы; структура не может определять конструктор (без параметров), и компиляторы не создают конструкторы без параметров для структур и других типов значений.If the source code for a structure defines constructors, they must be parameterized; a structure cannot define a parameterless constructor, and compilers do not generate parameterless constructors for structures or other value types. Все типы значений не имеют неявного конструктора без параметров.All value types do have an implicit parameterless constructor. Этот конструктор реализован средой CLR и инициализирует все поля структуры, задавая для них значения по умолчанию.This constructor is implemented by the common language runtime and initializes all fields of the structure to their default values.

СобытияEvents

Событие определяет происшествие, на которое можно реагировать, а также методы подписки, отказа от подписки или порождения события.An event defines an incident that can be responded to, and defines methods for subscribing to, unsubscribing from, and raising the event. События часто используются для оповещения других типов об изменениях состояния.Events are often used to inform other types of state changes. Дополнительные сведения см. в статье Events (Visual Basic) (События в Visual Basic).For more information, see Events.

Вложенные типыNested Types

Вложенный тип — это тип, являющийся членом какого-либо другого типа.A nested type is a type that is a member of some other type. Вложенные типы должны быть тесно связаны со своим вмещающим типом и не должны использоваться в качестве типа общего назначения.Nested types should be tightly coupled to their containing type and must not be useful as a general-purpose type. Вложенные типы полезны, когда объявляющий тип использует и создает экземпляры вложенного типа и использование вложенного типа не открывается в публичных членах.Nested types are useful when the declaring type uses and creates instances of the nested type, and use of the nested type is not exposed in public members.

Особенности вложенных типов не всегда понятны некоторым разработчикам; эти типы не должны быть открыто видимыми, если существенной причины для подобной видимости не имеется.Nested types are confusing to some developers and should not be publicly visible unless there is a compelling reason for visibility. В хорошо спроектированной библиотеке разработчикам редко приходится использовать вложенные типы для создания экземпляров объектов или объявления переменных.In a well-designed library, developers should rarely have to use nested types to instantiate objects or declare variables.

Характеристики членов типовCharacteristics of Type Members

Система общих типов CTS допускает наличие у членов типов различных характеристик, однако некоторые характеристики могут не поддерживаться в отдельных языках программирования.The common type system allows type members to have a variety of characteristics; however, languages are not required to support all these characteristics. В следующей таблице описаны характеристики членов.The following table describes member characteristics.

ХарактеристикаCharacteristic ПрименениеCan apply to ОписаниеDescription
abstractabstract Методы, свойства и событияMethods, properties, and events Тип не предоставляет реализацию метода.The type does not supply the method's implementation. Типы, которые наследуют или реализуют абстрактный метод, должны предоставлять реализацию метода.Types that inherit or implement abstract methods must supply an implementation for the method. Единственное исключение — когда производный тип является абстрактным.The only exception is when the derived type is itself an abstract type. Все абстрактные методы являются виртуальными.All abstract methods are virtual.
private, family, assembly, family and assembly, family or assembly, publicprivate, family, assembly, family and assembly, family or assembly, or public ВсеAll Определяют доступность члена.Defines the accessibility of the member:

privateprivate
Доступен только изнутри типа, к которому принадлежит член, или изнутри вложенного типа.Accessible only from within the same type as the member, or within a nested type.

familyfamily
Доступен изнутри типа, к которому принадлежит член, а также из производных от него типов.Accessible from within the same type as the member, and from derived types that inherit from it.

сборкаassembly
Доступен только в сборке, в которой определен тип.Accessible only in the assembly in which the type is defined.

family and assemblyfamily and assembly
Доступен только в типах с уровнем доступа family и assembly.Accessible only from types that qualify for both family and assembly access.

family or assemblyfamily or assembly
Доступен только в типах с уровнем доступа либо family, либо assembly.Accessible only from types that qualify for either family or assembly access.

publicpublic
Доступен в любом типе.Accessible from any type.
finalfinal Методы, свойства и событияMethods, properties, and events Виртуальный метод нельзя переопределить в производном типе.The virtual method cannot be overridden in a derived type.
initialize-onlyinitialize-only ПоляFields Значение можно только инициализировать и невозможно установить после инициализации.The value can only be initialized, and cannot be written after initialization.
экземплярinstance Поля, методы, свойства и событияFields, methods, properties, and events Если член не помечен как static (C# и C++), Shared (Visual Basic), virtual (C# и C++) или Overridable (Visual Basic), то он является членом экземпляра (ключевое слово instance не используется).If a member is not marked as static (C# and C++), Shared (Visual Basic), virtual (C# and C++), or Overridable (Visual Basic), it is an instance member (there is no instance keyword). Копий таких членов в памяти будет столько, сколько объектов их использует.There will be as many copies of such members in memory as there are objects that use it.
литералliteral ПоляFields Значение, присвоенное полю, является фиксированным значением встроенного типа значения и становится известным во время компиляции.The value assigned to the field is a fixed value, known at compile time, of a built-in value type. Поля литералов иногда называются константами.Literal fields are sometimes referred to as constants.
newslot или overridenewslot or override ВсеAll Определяет способ взаимодействия члена с унаследованными членами, имеющими ту же сигнатуру:Defines how the member interacts with inherited members that have the same signature:

newslotnewslot
Скрывает унаследованные члены с той же сигнатурой.Hides inherited members that have the same signature.

переопределенныйoverride
Заменяет определение наследуемого виртуального метода.Replaces the definition of an inherited virtual method.

По умолчанию используется характеристика newslot.The default is newslot.
статическийstatic Поля, методы, свойства и событияFields, methods, properties, and events Член принадлежит к типу, в котором он определен, а не к конкретному экземпляру типа. Член существует, даже если экземпляр типа не создан, и является общим для всех экземпляров типа.The member belongs to the type it is defined on, not to a particular instance of the type; the member exists even if an instance of the type is not created, and it is shared among all instances of the type.
виртуальныйvirtual Методы, свойства и событияMethods, properties, and events Метод может реализовываться с помощью производного типа и вызываться либо статически, либо динамически.The method can be implemented by a derived type and can be invoked either statically or dynamically. Если используется динамический вызов, то вызываемая реализация метода определяется типом экземпляра, выполняющего вызов во время выполнения, а не типом, известным во время компиляции.If dynamic invocation is used, the type of the instance that makes the call at run time (rather than the type known at compile time) determines which implementation of the method is called. Для статического вызова виртуального метода может потребоваться приведение переменной к типу, который использует нужную версию метода.To invoke a virtual method statically, the variable might have to be cast to a type that uses the desired version of the method.

ПерегрузкаOverloading

У каждого члена типа есть уникальная сигнатура.Each type member has a unique signature. Сигнатуры методов содержат имя метода и список параметров (порядок и типы аргументов метода).Method signatures consist of the method name and a parameter list (the order and types of the method's arguments). В типе можно определить несколько методов с одним именем и разными сигнатурами.Multiple methods with the same name can be defined within a type as long as their signatures differ. При этом метод будет называться перегруженным.When two or more methods with the same name are defined, the method is said to be overloaded. Например, в System.Char метод IsDigit перегружен.For example, in System.Char, the IsDigit method is overloaded. Один метод принимает параметр Char.One method takes a Char. Другой метод принимает String и Int32.The other method takes a String and an Int32.

Примечание

Тип возвращаемого значения не считается частью сигнатуры метода.The return type is not considered part of a method's signature. Это значит, что методы не могут быть перегружены, если они различаются только типом возвращаемого значения.That is, methods cannot be overloaded if they differ only by return type.

Наследование, переопределение и скрытие членовInheriting, Overriding, and Hiding Members

Производный тип наследует все члены своего базового типа. Эти члены будут определены для производного типа и доступны в нем.A derived type inherits all members of its base type; that is, these members are defined on, and available to, the derived type. Поведение или характеристики наследуемых членов можно изменить двумя способами.The behavior or qualities of inherited members can be modified in two ways:

  • В производном типе можно скрыть наследуемый член, определив новый член с такой же сигнатурой.A derived type can hide an inherited member by defining a new member with the same signature. Это может понадобиться для того, чтобы сделать ранее открытый член закрытым или определить новое поведение для унаследованного метода, помеченного как final.This might be done to make a previously public member private or to define new behavior for an inherited method that is marked as final.

  • Производный тип может переопределять наследуемый виртуальный метод.A derived type can override an inherited virtual method. Переопределяющий метод предоставляет новое определение метода, который будет вызываться, на основании типа значения во время выполнения, а не типа переменной, известной во время компиляции.The overriding method provides a new definition of the method that will be invoked based on the type of the value at run time rather than the type of the variable known at compile time. Метод может переопределить виртуальный метод только в том случае, если виртуальный метод не помечен как final, и при этом уровень доступности нового метода не ниже уровня доступности виртуального метода.A method can override a virtual method only if the virtual method is not marked as final and the new method is at least as accessible as the virtual method.

См. такжеSee also