Связанные и несвязанные типы — КиберПедия 

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...

Связанные и несвязанные типы

2017-10-16 261
Связанные и несвязанные типы 0.00 из 5.00 0 оценок
Заказать работу

Термин несвязанный тип обозначает не являющийся универсальным тип или несвязанный универсальный тип. Термин связанный тип обозначает не являющийся универсальным тип или сформированный тип.

Несвязанный тип ссылается на сущность, описанную в объявлении типа. Несвязанный универсальный тип сам по себе не является типом и не может использоваться в качестве типа переменной, аргумента или возвращаемого значения, а также в качестве базового типа. Несвязанный универсальный тип может использоваться только в выражениях typeof (§7.6.11).

Соблюдение ограничений

При каждом использовании сформированного типа или универсального метода выполняется проверка предоставленных аргументов типа на предмет соответствия ограничениям, накладываемым на параметры типа при объявлении универсального типа или метода (§10.1.5). Для каждого предложения where выполняется проверка аргумента типа A, соответствующего параметру именованного типа, следующим образом:

· Если ограничение представляет собой тип класса, тип интерфейса или параметр типа, определяется тип C, представляющий это ограничение. Предоставленные аргументы типа замещают любые параметры типа, указанные в ограничении. Соответствие ограничению соблюдается только в том случае, если тип A можно преобразовать к типу C с помощью любого из следующих преобразований:

o Преобразование идентификации (§6.1.1).

o Неявное преобразование ссылочного типа (§6.1.6)

o Преобразование упаковки (§6.1.7), если тип A представляет собой необнуляемый тип значений.

o Неявное преобразование ссылочного типа, упаковки или параметра типа из параметра типа A в C.

· Если ограничение является ограничением ссылочного типа (class), тип A должен соответствовать одному из следующих ограничений:

o Тип A является типом интерфейса, класса, делегата или массива. Обратите внимание, что типы System.ValueType и System.Enum являются ссылочными типами, которые соответствуют этому ограничению.

o Тип A представляет собой параметр типа, являющегося ссылочным типом (§10.1.5).

· Если ограничение является ограничением типа значений (struct), тип A должен соответствовать одному из следующих ограничений:

o Тип A является типом структуры или перечисляемым типом и не является обнуляемым типом. Обратите внимание, что типы System.ValueType и System.Enum являются ссылочными типами, которые не соответствуют этому ограничению.

o Тип A представляет собой параметр типа, для которого определено ограничение типа значений (§10.1.5).

· Если ограничение является ограничением конструктора new(), тип A не может представлять класс abstract и должен включать не содержащий параметров открытый конструктор. Соответствие этому ограничению обеспечивается в том случае, если верно одно из следующих утверждений:

o Тип A является типом значений, поскольку все типы значений содержат открытый конструктор по умолчанию (§4.1.2).

o Тип A представляет собой параметр типа, для которого определено ограничение конструктора (§10.1.5).

o Тип A представляет собой параметр типа, для которого определено ограничение типа значений (§10.1.5).

o Тип A представляет собой класс, отличный от abstract, который содержит явно объявленный конструктор public, не имеющий параметров.

o Тип A не является классом abstract и содержит конструктор по умолчанию (§10.11.4).

Если для указанных аргументов типа не соблюдаются одно или несколько ограничений параметров типа, возникает ошибка времени компиляции.

Поскольку наследование параметров типа не поддерживается, наследование ограничений также невозможно. В приведенном ниже примере требуется задать ограничение для параметра типа T типа D. При этом параметр T должен соответствовать ограничению, заданному в базовом классе B<T>. Напротив, для класса E не требуется задавать ограничение, поскольку List<T> реализует IEnumerable для любого T.

class B<T> where T: IEnumerable {...}

class D<T>: B<T> where T: IEnumerable {...}

class E<T>: B<List<T>> {...}

Параметры типа

Параметр типа представляет собой идентификатор, определяющий тип значений или ссылочный тип, с которым параметр связан во время выполнения.

type-parameter:
identifier

Поскольку экземпляр параметра типа может быть создан с несколькими различными аргументами фактического типа, операции и ограничения, присущие параметрам типа, несколько отличаются от других типов. Основные отличия:

· Не допускается прямое использование параметра типа для объявления базового класса (§10.2.4) или интерфейса (§13.1.3).

· Правила поиска членов для параметров типа определяются применяемыми к ним ограничениями (при наличии таковых). Дополнительные сведения об ограничениях см. в разделе §7.4.

· Доступные преобразования для параметров типа определяются применяемыми к ним ограничениями (при наличии таковых). Дополнительные сведения о преобразованиях см. в разделах §6.1.10 и §6.2.6.

· Литерал null не может быть преобразован к типу, задаваемому параметром типа, за исключением случаев, когда параметр является ссылочным типом (§6.1.10). Вместо этого можно использовать выражение default (§7.6.13). Кроме того, если для параметра типа не предусмотрено ограничение типа значений, можно сравнить значение, которое имеет тип, задаваемый параметром типа, со значением null с помощью операторов == и!= (§7.10.6).

· Выражение new (§7.6.10.1) может использоваться только с параметром типа, для которого предусмотрено ограничение конструктора или ограничение типа значений (§10.1.5).

· Параметр типа не может использоваться в атрибутах.

· Параметр типа не может использоваться при доступе к члену (§7.6.4) или в имени типа (§3.8) для определения статического члена или вложенного типа.

· В небезопасном коде не допускается использование параметра типа в качестве неуправляемого типа (§18.2).

Являясь типом, параметр типа представляет собой конструкцию, существующую исключительно во время компиляции. Во время выполнения каждый параметр типа связан с типом времени выполнения, заданным с помощью аргумента типа в объявлении универсального типа. Таким образом, переменная, объявленная с помощью параметра типа, во время выполнения будет иметь закрытый сформированный тип (§4.4.2). Во время выполнения для операторов и выражений, содержащих параметры типа, используются фактические типы, предоставленные в качестве аргументов типа для этих параметров.

Типы дерева выражений

Деревья выражений обеспечивают представление лямбда-выражений в виде структур данных вместо исполняемого кода. Дерево выражений представляет собой значение типа дерева выражения вида System.Linq.Expressions.Expression<D>, где D — любой тип делегата. Далее в этой спецификации такие типы будут обозначаться с помощью сокращенной формы Expression<D>.

Если для лямбда-выражения существует преобразование к типу делегата D, для нее также существует и преобразование к типу дерева выражений Expression<D>. В результате преобразования лямбда-выражения к типу делегата создается делегат, содержащий ссылки на исполняемый код этого лямбда-выражения. При преобразовании лямбда-выражения к типу дерева выражений создается представление этого лямбда-выражения в виде дерева выражений.

Дерево выражений является эффективным представлением данных лямбда-выражения в памяти, обеспечивающим прозрачное и явное представление структуры этого выражения.

Аналогично типу делегата D, тип Expression<D> обладает типами параметров и возвращаемых значений, которые совпадают с параметрами типа D.

В приведенном ниже примере лямбда-выражение представляется как в виде исполняемого кода, так и в виде дерева выражений. Поскольку существует преобразование к Func<int,int>, также существует и преобразование к Expression<Func<int,int>>:

Func<int,int> del = x => x + 1; // Code

Expression<Func<int,int>> exp = x => x + 1; // Data

В результате этих присвоений делегат del содержит ссылку на метод, который возвращает x + 1, а дерево выражений exp содержит ссылку на структуру данных, описывающую выражение x => x + 1.

Точное определение универсального типа Expression<D>, а также точные правила построения дерева выражений при преобразовании лямбда-выражения к типу дерева выражений описываются в соответствующей документации.

Следует обратить внимание на следующие моменты:

  • Не все лямбда-выражения можно преобразовывать в деревья выражений. Например, не поддерживается представление лямбда-выражений, содержащих тела оператора и выражения присваивания. В этих случаях преобразование по-прежнему существует, однако вызывает ошибку во время компиляции. Подробное описание этих исключений см. в разделе §6.5.
  • Тип Expression<D> содержит метод экземпляра Compile, порождающий делегат типа D:

Func<int,int> del2 = exp.Compile();

При вызове этого делегата выполняется код, представленный деревом выражений. Таким образом, учитывая приведенные выше определения, del и del2 являются эквивалентными, то есть выполнение приведенных ниже операторов имеет одинаковый эффект:

int i1 = del(1);

int i2 = del2(1);

После выполнения этого кода переменным i1 и i2 присваивается значение 2.

Динамический тип

Тип dynamic в C# имеет особое значение. Он необходим для обеспечения возможности динамической привязки, которая описана подробно в §7.2.2.

Тип dynamic считается идентичным типу object за исключением следующих случаев:

· если операции и выражения типа dynamic могут быть использованы в динамической привязке (§7.2.2);

· вывод типа (§7.5.2) предпочтет тип dynamic типу object при наличии обоих вариантов.

Ввиду этой равнозначности, верно, что:

· Существует неявное тождественное преобразование между типами object и dynamic, а также между сформированными типами, которые не изменяются при замене типа dynamic на тип object.

· Явные и неявные преобразования из типа object и к этому типу также применяются для преобразования к типу dynamic и из этого типа.

· Сигнатуры метода, которые являются теми же, когда заменяют тип dynamic на тип object, считаются теми же сигнатурами.

Тип dynamic не отличается от типа object во время выполнения.

Выражение типа dynamic указывает на то, что это динамическое выражение.

Переменные

Переменные указывают места хранения данных. Каждая переменная имеет тип, который определяет, какие значения могут храниться в этой переменной. В языке C# все данные должны относиться к определенному типу, компилятор C# обеспечивает соответствие типа значений, хранящихся в переменных. Значение переменной можно изменить путем присваивания или при помощи операторов ++ и ‑‑.

Получить значение переменной можно только в том случае, если она является определенно присвоенной (§5.3).

Как рассматривается в следующих разделах, переменные подразделяются на переменные с начальным значением и переменные без начального значения. Переменная с начальным значением имеет должным образом определенное исходное значение и всегда считается определенно присвоенной. У переменной без начального значения исходное значение отсутствует. Чтобы переменная без начального значения считалась определенно присвоенной в конкретном месте, необходимо присвоить этой переменной значение в каждом возможном пути выполнения, ведущем к указанному месту.

Категории переменных

В C# определено семь категорий переменных: статические переменные, переменные экземпляра, элементы массива, параметры по значению, параметры по ссылке, выходные параметры и локальные переменные. Эти категории рассматриваются в следующих ниже разделах.

В этом примере

class A
{
public static int x;
int y;

void F(int[] v, int a, ref int b, out int c) {
int i = 1;
c = a + b++;
}
}

Переменная x является статической переменной, y — переменной экземпляра, v[0] — элементом массива, a — параметром по значению, b — параметром по ссылке, c — выходным параметром, а i — локальной переменной.

Статические переменные

Поле, объявленное с модификатором static, называется статической переменной. Статическая переменная создается перед выполнением статического конструктора (§10.12) для содержащегося в ней типа и прекращает свое существование при удалении домена связанного приложения.

Начальным значением статической переменной является значение, установленное по умолчанию для соответствующего типа переменных (§5.2).

Для целей проверки определенного присваивания статическая переменная считается переменной с начальным значением.

Переменные экземпляра

Поле, объявленное без модификатора static, называется переменной экземпляра.


Поделиться с друзьями:

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.037 с.