Встроенные ссылочные типы (справочник по C#)Built-in reference types (C# reference)

В C# есть ряд встроенных ссылочных типов.C# has a number of built-in reference types. У них есть ключевые слова или операторы, которые являются синонимами типа в библиотеке .NET.They have keywords or operators that are synonyms for a type in the .NET library.

Тип objectThe object type

Тип object является псевдонимом System.Object в .NET.The object type is an alias for System.Object in .NET. В унифицированной системе типов C# все типы, стандартные и определяемые пользователем, ссылочные типы и типы значений напрямую или косвенно наследуются из System.Object.In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from System.Object. Переменным типа object можно назначать значения любого типа.You can assign values of any type to variables of type object. Любой переменной object можно назначить значение по умолчанию с помощью литерала null.Any object variable can be assigned to its default value using the literal null. Если переменная типа значения преобразуется в объект, она считается упакованной .When a variable of a value type is converted to object, it is said to be boxed . Если переменная типа object преобразуется в тип значения, она считается распакованной .When a variable of type object is converted to a value type, it is said to be unboxed . Дополнительные сведения см. в разделе Упаковка-преобразование и распаковка-преобразование.For more information, see Boxing and Unboxing.

Тип stringThe string type

Тип string представляет последовательность, состоящую из нуля или более символов в кодировке Юникод.The string type represents a sequence of zero or more Unicode characters. string является псевдонимом для System.String в .NET.string is an alias for System.String in .NET.

Несмотря на то что string представляет собой ссылочный тип, операторы равенства == и != по определению сравнивают не ссылки, а значения объектов string.Although string is a reference type, the equality operators == and != are defined to compare the values of string objects, not references. Это делает проверку равенства строк более интуитивно понятной.This makes testing for string equality more intuitive. Пример:For example:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine(object.ReferenceEquals(a, b));

Отображается значение True, а затем False, поскольку содержимое строк эквивалентно, однако a и b не относятся к одному и тому же экземпляру строки.This displays "True" and then "False" because the content of the strings are equivalent, but a and b do not refer to the same string instance.

Оператор + объединяет строки:The + operator concatenates strings:

string a = "good " + "morning";

При этом создается строковый объект, содержащий слова "good morning".This creates a string object that contains "good morning".

Строки неизменяемы , т. е. содержимое созданного строкового объекта изменить нельзя, хотя синтаксис выглядит так, будто это возможно.Strings are immutable --the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this. Например, при написании кода компилятор фактически создает новый строковый объект для хранения новой последовательности символов, а затем этот новый объект назначается b.For example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to b. Память, выделенная для b (если он содержит строку h), затем доступна для сборки мусора.The memory that had been allocated for b (when it contained the string "h") is then eligible for garbage collection.

string b = "h";
b += "ello";

Оператор[] позволяет предоставить к отдельным символам строки доступ только на чтение.The [] operator can be used for readonly access to individual characters of a string. Допустимые значения индекса начинаются с 0 и должны быть меньше, чем длина строки:Valid index values start at 0 and must be less than the length of the string:

string str = "test";
char x = str[2];  // x = 's';

Также оператор [] можно использовать для итерации каждого символа в строке:In similar fashion, the [] operator can also be used for iterating over each character in a string:

string str = "test";

for (int i = 0; i < str.Length; i++)
{
  Console.Write(str[i] + " ");
}
// Output: t e s t

Строковые литералы имеют тип string и могут быть записаны в двух формах: в кавычках (") или в кавычках с префиксом @.String literals are of type string and can be written in two forms, quoted and @-quoted. Строковые литералы в кавычках заключаются в двойные кавычки ("):Quoted string literals are enclosed in double quotation marks ("):

"good morning"  // a string literal

Строковые литералы могут содержать любые символьные литералы.String literals can contain any character literal. Escape-последовательности включены.Escape sequences are included. В следующем примере escape-последовательность \\ используется для получения обратной косой черты, \u0066 — для получения буквы f, и \n — для получения новой строки.The following example uses escape sequence \\ for backslash, \u0066 for the letter f, and \n for newline.

string a = "\\\u0066\n F";
Console.WriteLine(a);
// Output:
// \f
//  F

Примечание

Escape-код \udddd (где dddd состоит из четырех цифр) представляет символ Юникода U+dddd.The escape code \udddd (where dddd is a four-digit number) represents the Unicode character U+dddd. Также распознаются восьмизначные escape-коды Юникода: \Udddddddd.Eight-digit Unicode escape codes are also recognized: \Udddddddd.

Буквальные строковые литералы начинаются с @ и также заключаются в двойные кавычки.Verbatim string literals start with @ and are also enclosed in double quotation marks. Пример:For example:

@"good morning"  // a string literal

Преимущество буквальных строк состоит в том, что escape-последовательности не обрабатываются, что позволяет легко написать, например, полное имя файла Windows:The advantage of verbatim strings is that escape sequences are not processed, which makes it easy to write, for example, a fully qualified Windows file name:

@"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

Чтобы добавить в строку @-quoted двойные кавычки, продублируйте этот символ:To include a double quotation mark in an @-quoted string, double it:

@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.

Тип delegateThe delegate type

Объявление типа делегата аналогично сигнатуре метода.The declaration of a delegate type is similar to a method signature. Оно имеет возвращаемое значение и любое число параметров любого типа:It has a return value and any number of parameters of any type:

public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);

В .NET типы System.Action и System.Func предоставляют общие определения для многих распространенных делегатов.In .NET, System.Action and System.Func types provide generic definitions for many common delegates. Скорее всего, не нужно определять новые пользовательские типы делегата.You likely don't need to define new custom delegate types. Вместо этого можно создать экземпляры предоставленных универсальных типов.Instead, you can create instantiations of the provided generic types.

Ключевое слово delegate имеет ссылочный тип, который можно использовать для инкапсуляции именованного или анонимного метода.A delegate is a reference type that can be used to encapsulate a named or an anonymous method. Делегаты аналогичны используемым в языке C++ указателям функций, но являются типобезопасными и безопасными.Delegates are similar to function pointers in C++; however, delegates are type-safe and secure. Сведения о применении делегатов см. в разделах Делегаты и Универсальные делегаты.For applications of delegates, see Delegates and Generic Delegates. Делегаты являются основой событий.Delegates are the basis for Events. Экземпляры делегата могут создаваться путем его связывания с именованным или анонимным методом.A delegate can be instantiated by associating it either with a named or anonymous method.

Делегат должен быть создан при помощи метода или лямбда-выражения, имеющего совместимые возвращаемый тип и входные параметры.The delegate must be instantiated with a method or lambda expression that has a compatible return type and input parameters. Дополнительные сведения о допустимой степени вариации сигнатур методов см. в разделе Вариативность в делегатах.For more information on the degree of variance that is allowed in the method signature, see Variance in Delegates. Для использования с анонимными методами делегат и код, который должен быть связан с ним, должны быть объявлены вместе.For use with anonymous methods, the delegate and the code to be associated with it are declared together.

Тип dynamicThe dynamic type

Тип dynamic указывает, что использование переменной и ссылок на ее члены обходит проверку типа во время компиляции.The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. Такие операции разрешаются во время выполнения.Instead, these operations are resolved at run time. Тип dynamic упрощает доступ к API COM, таким как API автоматизации Office, к динамическим API, таким как библиотеки IronPython, и к HTML-модели DOM.The dynamic type simplifies access to COM APIs such as the Office Automation APIs, to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).

Тип dynamic в большинстве случаев ведет себя как тип object.Type dynamic behaves like type object in most circumstances. В частности, можно преобразовать любое выражение, отличное от NULL, в тип dynamic.In particular, any non-null expression can be converted to the dynamic type. Тип dynamic отличается от object тем, что операции, которые содержат выражения типа dynamic, не разрешаются или тип проверяется компилятором.The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. Компилятор объединяет сведения об операции, которые впоследствии будут использоваться для оценки этой операции во время выполнения.The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. В рамках этого процесса переменные типа dynamic компилируются в переменные типа object.As part of the process, variables of type dynamic are compiled into variables of type object. Таким образом, тип dynamic существует только во время компиляции, но не во время выполнения.Therefore, type dynamic exists only at compile time, not at run time.

В следующем примере переменной типа dynamic противопоставляется переменная типа object.The following example contrasts a variable of type dynamic to a variable of type object. Чтобы проверить тип каждой переменной во время компиляции, наведите указатель мыши на dyn или obj в операторах WriteLine.To verify the type of each variable at compile time, place the mouse pointer over dyn or obj in the WriteLine statements. Скопируйте следующий код в редактор, где доступен IntelliSense.Copy the following code into an editor where IntelliSense is available. IntelliSense отображает dynamic для dyn и object для obj.IntelliSense shows dynamic for dyn and object for obj.

class Program
{
    static void Main(string[] args)
    {
        dynamic dyn = 1;
        object obj = 1;

        // Rest the mouse pointer over dyn and obj to see their
        // types at compile time.
        System.Console.WriteLine(dyn.GetType());
        System.Console.WriteLine(obj.GetType());
    }
}

Операторы WriteLine отображают типы времени выполнения dyn и obj.The WriteLine statements display the run-time types of dyn and obj. На этом этапе оба имеют один и тот же тип — целое число.At that point, both have the same type, integer. Выводятся следующие результаты.The following output is produced:

System.Int32
System.Int32

Чтобы увидеть разницу между dyn и obj во время компиляции, добавьте между объявлениями и операторами WriteLine в предыдущем примере следующие две строки:To see the difference between dyn and obj at compile time, add the following two lines between the declarations and the WriteLine statements in the previous example.

dyn = dyn + 3;
obj = obj + 3;

При попытке добавления целого числа и объекта в выражение obj + 3 выдается ошибка компилятора.A compiler error is reported for the attempted addition of an integer and an object in expression obj + 3. При этом для dyn + 3 ошибка не возникает.However, no error is reported for dyn + 3. Выражение, которое содержит dyn, не проверяется во время компиляции, поскольку тип dyn имеет значение dynamic.The expression that contains dyn is not checked at compile time because the type of dyn is dynamic.

В следующем примере dynamic используется в нескольких объявлениях.The following example uses dynamic in several declarations. Метод Main также противопоставляет проверку типов во время компиляции.The Main method also contrasts compile-time type checking with run-time type checking.

using System;

namespace DynamicExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            ExampleClass ec = new ExampleClass();
            Console.WriteLine(ec.exampleMethod(10));
            Console.WriteLine(ec.exampleMethod("value"));

            // The following line causes a compiler error because exampleMethod
            // takes only one argument.
            //Console.WriteLine(ec.exampleMethod(10, 4));

            dynamic dynamic_ec = new ExampleClass();
            Console.WriteLine(dynamic_ec.exampleMethod(10));

            // Because dynamic_ec is dynamic, the following call to exampleMethod
            // with two arguments does not produce an error at compile time.
            // However, it does cause a run-time error.
            //Console.WriteLine(dynamic_ec.exampleMethod(10, 4));
        }
    }

    class ExampleClass
    {
        static dynamic field;
        dynamic prop { get; set; }

        public dynamic exampleMethod(dynamic d)
        {
            dynamic local = "Local variable";
            int two = 2;

            if (d is int)
            {
                return local;
            }
            else
            {
                return two;
            }
        }
    }
}
// Results:
// Local variable
// 2
// Local variable

См. такжеSee also