Числовое расширение унарных операторов — КиберПедия 

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

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

Числовое расширение унарных операторов

2017-10-16 280
Числовое расширение унарных операторов 0.00 из 5.00 0 оценок
Заказать работу

Числовое расширение унарных операторов выполняется для операндов стандартных унарных операторов +, – и ~. Числовое расширение унарных операторов заключается в простом преобразовании операндов типа sbyte, byte, short, ushort или char в тип int. Кроме того, для унарного оператора – при числовом расширении унарного оператора происходит преобразование операндов с типом uint в тип long.

Числовое расширение бинарных операторов

Числовое расширение бинарных операторов выполняется для операндов стандартных бинарных операторов +, –, *, /, %, &, |, ^, ==,!=, >, <, >= и <=. При числовом расширении бинарных операторов оба операнда преобразуются в общий тип. Для операторов, отличных от операторов отношения, этот тип становится типом результата операции. Числовое расширение бинарных операторов состоит в применении следующих правил в указанном здесь порядке.

· Если один из операндов имеет тип decimal, то другой операнд преобразуется в тип decimal, либо если другой операнд имеет тип float или double, то возникает ошибка времени привязки.

· Иначе, если один из операндов имеет тип double, то другой операнд преобразуется в тип double.

· Иначе, если один из операндов имеет тип float, то другой операнд преобразуется в тип float.

· В противном случае, если один из операндов имеет тип ulong, то другой операнд преобразуется в тип ulong, либо, если другой операнд имеет тип sbyte, short, int или long, возникает ошибка времени привязки.

· Иначе, если один из операндов имеет тип long, то другой операнд преобразуется в тип long.

· В противном случае, если один из операндов имеет тип uint, а другой операнд — тип sbyte, short или int, оба операнда преобразуются в тип long.

· Иначе, если один из операндов имеет тип uint, то другой операнд преобразуется в тип uint.

· Иначе оба операнда преобразуются в тип int.

Обратите внимание, что первое правило запрещает любые операции, в которых смешиваются тип decimal и типы double и float. Это правило вытекает из того факта, что неявное преобразование между типом decimal и типом double или float не существует.

Также обратите внимание, что операнд не может иметь тип ulong, когда другой операнд имеет целый тип со знаком. Это так, поскольку не существует целого типа, который может представлять полный спектр значений ulong вместе с целыми типами со знаком.

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

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

decimal AddPercent(decimal x, double percent) {
return x * (1.0 + percent / 100.0);
}

возникает ошибка времени привязки, поскольку значения типа decimal нельзя умножать на значение типа double. Эта ошибка устраняется с помощью явного преобразования второго операнда в тип decimal, ср.:

decimal AddPercent(decimal x, double percent) {
return x * (decimal)(1.0 + percent / 100.0);
}

Операторы с нулификацией

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

· Для унарных операторов

+ ++ - --! ~

вариант оператора с нулификацией существует, если типы операнда и результата оба являются необнуляемыми типами значений. Вариант оператора с нулификацией создается с помощью добавления одного модификатора? к типу операнда и результата. Значением оператора с нулификацией является значение null, если операнд равен null. В противном случае в операторе с нулификацией с операнда снимается упаковка, применяется базовый оператор и затем создается упаковка для результата.

· Для бинарных операторов.

+ - * / % & | ^ << >>

вариант оператора с нулификацией существует, если типы операнда и результата являются необнуляемыми типами значений. Вариант оператора с нулификацией создается с помощью добавления одного модификатора? к типу каждого операнда и результата. Значением оператора с нулификацией является значение NULL, если один или оба операнда равны NULL (исключение составляют операторы & и | типа bool?, см. раздел §7.11.3). В противном случае в операторе с нулификацией с операндов снимается упаковка, применяется базовый оператор и затем создается упаковка для результата.

· Для операторов равенства

==!=

вариант оператора с нулификацией существует, если оба операнда имеют необнуляемый тип значений, а результат имеет тип bool. Вариант оператора с нулификацией создается с помощью добавления одного модификатора? к каждому типу операнда. В операторе с нулификацией равными считаются два значения null, а неравными — значение null и любое другое ненулевое значение. Если оба операнда не равны NULL, то в операторе с нулификацией с операндов снимается упаковка и для получения результата с типом bool применяется базовый оператор.

· Для операторов отношения

< > <= >=

вариант оператора с нулификацией существует, если оба операнда имеют необнуляемый тип значений, а результат имеет тип bool. Вариант оператора с нулификацией создается с помощью добавления одного модификатора? к каждому типу операнда. Значением оператора с нулификацией является false, если один или оба операнда имеют значение NULL. В противном случае в операторе с нулификацией с операндов снимается упаковка и для получения результата с типом bool применяется базовый оператор.

Поиск членов

Поиск членов— это процесс, при котором определяется значение имени в контексте данного типа. Поиск членов может выполняться в составе процесса вычисления простого имени (§7.6.2) или доступа к члену (§7.6.4) в выражении. Если простое имя или доступ к члену указывается в виде простого выражения для выражения вызова (§7.6.5.1), то говорят, что этот член вызываемый.

Если член является методом или событием или если он является константой, полем или свойством либо типа делегата (§15), либо типа dynamic (§4.7), то говорят, что этот метод допускает вызов.

При поиске членов учитывается не только имя члена, но также и число параметров типа, имеющихся у члена, а также, доступен ли член. Для поиска членов в универсальных методах и во вложенных универсальных методах в соответствующих объявлениях указывается определенное число параметров типа, а у всех остальных членов параметров типа нет.

Поиск члена с именем N и параметрами типа K в типе T происходит следующим образом.

· Сначала определяется набор доступных членов с именем N.

o Если T — это параметр типа, то такой набор представляет собой объединение наборов доступных членов с именем N из каждого типа, указанного в качестве первичного или вторичного ограничения (§10.1.5) для T, вместе с набором доступных членов с именем N в object.

o В противном случае набор состоит из всех доступных членов (§3.5) с именем N в типе T, включая унаследованные члены и доступные члены с именем N в типе object. Если T — это сформированный тип, то набор членов получается заменой аргументов типа, как описано разделе в §10.3.2. Из набора исключаются члены с модификатором override.

· Затем, если K равно нулю, удаляются все вложенные типы, в объявления которых входят параметры типа. Если K не равно нулю, удаляются все члены с отличающимся числом параметров типа. Обратите внимание, что когда K равно нулю, методы с параметрами типа не удаляются, поскольку в процессе определения типа (§7.5.2) могут выводиться аргументы типа.

· Затем, если метод является вызываемым, из набора удаляются все не допускающие вызов члены.

· Затем из набора удаляются члены, скрытые другими членами. Для каждого члена S.M в наборе, где S — это тип, в котором определен член M, применяются следующие правила.

o Если M является константой, полем, свойством, событием или элементом перечисления, из набора удаляются все члены, объявленные в базовом типе S.

o Если M является объявлением типа, из набора удаляются все объявленные в базовом типе S члены, не являющиеся типами, а также все объявления типов с таким же числом параметров типа, как и в M, объявленные в базовом типе S.

o Если M является методом, то из набора удаляются все объявленные в базовом типе S члены, не являющиеся методами.

· Затем из набора удаляются члены интерфейса, скрытые членами класса. Этот шаг выполняется, только если T является параметром типа и у T есть как действительный базовый класс, отличный от класса object, так и действительный непустой набор интерфейсов (§10.1.5). Для каждого члена S.M в наборе, где S — это тип, в котором определен член M, применяются следующие правила, если S является объявлением класса, отличного от object.

o Если M является константой, полем, свойством, событием, элементом перечисления или объявлением типа, из набора удаляются все члены, объявленные в объявлении интерфейса.

o Если M является методом, из набора удаляются все объявленные в объявлении интерфейса члены, не являющиеся методами, а также все объявленные в объявлении интерфейса методы с такой же подписью, как и у M.

· Наконец, после удаления скрытых членов определяется результат поиска.

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

o Иначе, если набор содержит только методы, то эта группа методов является результатом поиска.

o Иначе поиск привел к неоднозначным результатам, что вызывает ошибку времени привязки.

При поиске членов в типах, отличных от параметров типа и интерфейсов, а также поиске членов в интерфейсах со строго единственным наследованием (каждый интерфейс в цепочке наследования имеет единственный непосредственный базовый интерфейс или не имеет такого) в результате применения правил поиска происходит простое скрытие базовых членов производными членами с такими же именами. При поиске в случае строго единственного наследования неоднозначности никогда не возникает. Случаи неоднозначности, которые могут возникать при поиске членов в случае с множественным наследованием, описываются в разделе §13.2.5.

Базовые типы

Для поиска членов считается, что у типа T есть следующие базовые типы:

· Если T имеет тип object, у T нет базового типа.

· Если T имеет тип перечисления, то базовыми типами T являются типы классов System.Enum, System.ValueType и object.

· Если T имеет тип структуры, то базовыми типами T являются типы классов System.ValueType и object.

· Если T имеет тип класса, то базовыми классами T являются базовые классы T, включая тип класса object.

· Если T имеет тип интерфейса, то базовыми классами T являются базовые интерфейсы T и тип класса object.

· Если T имеет тип массива, то базовыми типами T являются типы классов System.Array и object.

· Если T имеет тип делегата, то базовыми типами T являются типы классов System.Delegate и object.

Функции-члены

Функции-члены — это члены, содержащие исполняемые операторы. Функции-члены всегда являются членами типов и не могут быть членами пространств имен. В C# определены следующие категории функций-членов:

· Методы

· Свойства

· События

· Индексаторы

· Пользовательские операторы

· Конструкторы экземпляров

· Статические конструкторы

· Деструкторы

За исключением деструкторов и статических конструкторов (которые нельзя вызывать явно) операторы в функциях-членах выполняются при вызовах функции-члена. Фактический синтаксис вызова функции-члена зависит от конкретной категории функции-члена.

Список аргументов (§7.5.1) для функции-члена содержит фактические значения или ссылки на переменные для параметров функции-члена.

Вызовы универсальных методов могут использовать выводы типа для определения набора типов аргументов для выполнения метода. Этот процесс описывается в разделе §7.5.2.

При вызове методов, индексаторов, операторов и конструкторов экземпляров выполняется разрешение перегрузки с целью определить, какой набор кандидатов функций-членов будет вызываться. Этот процесс описывается в разделе §7.5.3.

После определения конкретной функции-члена во время привязки (возможно, в процессе разрешения перегрузки), фактический процесс вызова функции-члена во время выполнения описывается в разделе §7.5.4.

В следующей таблице приводится сводка по операциям, которые выполняются в конструкциях с шестью категориями функций-членов, допускающих явный вызов. В таблице e, x, y и value обозначают выражения с типом переменной или значения, T означает выражение типа, F — это простое имя метода, а P — это простое имя свойства.

 

Конструкция Пример Описание
Вызов метода F(x, y) Для выбора наиболее подходящего метода F в содержащем классе или структуре используется разрешение перегрузки. Метод вызывается со списком аргументов (x, y). Если у метода нет модификатора static, выражением экземпляра является this.
T.F(x, y) Для выбора наиболее подходящего метода F в классе или структуре T используется разрешение перегрузки. Если метод не относится к типу static, возникает ошибка времени привязки. Метод вызывается со списком аргументов (x, y).
e.F(x, y) Для выбора наиболее подходящего метода F в классе, структуре или интерфейсе, передаваемом в типе e используется разрешение перегрузки. Если метод относится к типу static, возникает ошибка времени привязки. Метод вызывается с выражением экземпляра e и со списком аргументов (x, y).
Доступ к свойству P В содержащем классе или структуре вызывается метод доступа get свойства P. Если свойство P доступно только для записи, то возникает ошибка времени компиляции. Если у P нет модификатора static, выражением экземпляра является this.
P = value В содержащем классе или структуре вызывается метод доступа set свойства P со списком аргументов (value). Если свойство P доступно только для чтения, то возникает ошибка времени компиляции. Если у P нет модификатора static, выражением экземпляра является this.
T.P В классе или структуре T вызывается метод доступа get свойства P. Если у свойства P нет модификатора static или свойство P доступно только для записи, возникает ошибка времени компиляции.
T.P = value В классе или структуре T вызывается метод доступа set свойства P со списком аргументов (value). Если у свойства P нет модификатора static или свойство P доступно только для чтения, возникает ошибка времени компиляции.
e.P В классе, структуре или интерфейсе, передаваемом по типу e, вызывается метод доступа get свойства P с выражением экземпляра e. Если свойству P присвоен модификатор static или свойство P доступно только для записи, возникает ошибка времени привязки.
e.P = value В классе, структуре или интерфейсе, передаваемом по типу e, вызывается метод доступа set свойства P с выражением экземпляра e и списком аргументов (value). Если свойству P присвоен модификатор static или свойство P доступно только для чтения, возникает ошибка времени привязки.
Доступ к событию E += value В содержащем классе или структуре вызывается метод доступа add события E. Если событие E не относится к типу static, то выражением экземпляра является this.
E -= value В содержащем классе или структуре вызывается метод доступа remove события E. Если событие E не относится к типу static, то выражением экземпляра является this.
T.E += value В классе или структуре T вызывается метод доступа add события E. Ошибка времени привязки возникает, если E не является статическим.
T.E -= value В классе или структуре T вызывается метод доступа remove события E. Ошибка времени привязки возникает, если E не является статическим.
e.E += value В классе, структуре или интерфейсе, передаваемом по типу e, вызывается метод доступа add события E с выражением экземпляра e. Если событие E не относится к типу static, возникает ошибка времени привязки.
e.E -= value В классе, структуре или интерфейсе, передаваемом по типу e, вызывается метод доступа remove события E с выражением экземпляра e. Если событие E не относится к типу static, возникает ошибка времени привязки.
Доступ к индексатору e[x, y] Разрешение перегрузки применяется для выбора лучшего индексатора в классе, структуре или интерфейсе, предоставленном типом e. Метод доступа get индексатора вызывается выражением экземпляра e и списком аргументов (x, y). Если индексатор доступен только на запись, то возникает ошибка времени привязки.
e[x, y] = value Для выбора наиболее подходящего индексатора в классе, структуре или интерфейсе, передаваемом в типе e, используется разрешение перегрузки. Вызывается метод доступа set индексатора с выражением экземпляра e и со списком аргументов (x, y, value). Если индексатор доступен только на чтение, то возникает ошибка времени привязки.
Вызов оператора -x Для выбора наиболее подходящего унарного оператора в классе или структуре, передаваемой в типе x, используется разрешение перегрузки. Выбранный оператор вызывается со списком аргументов (x).
x + y Для выбора наиболее подходящего бинарного оператора в классах или структурах, передаваемых в типах x и y, используется разрешение перегрузки. Выбранный оператор вызывается со списком аргументов (x, y).
Вызов конструктора экземпляра new T(x, y) Для выбора наиболее подходящего конструктора экземпляра в классе или структуре T используется разрешение перегрузки. Конструктор экземпляра вызывается со списком аргументов (x, y).

 

Списки аргументов

Каждый вызов функции-члена и делегата включает список аргументов, в котором передаются фактические параметры или ссылки на переменные для параметров функции-члена. Синтаксис записи списка аргументов при вызове функции-члена зависит от категории функции-члена.

· Для конструкторов экземпляров, методов, индексаторов и делегатов аргументы указываются в виде списка аргументов, как показано ниже. Для индексаторов при вызове метода доступа set список аргументов дополнительно включает выражение, указанное в качестве правого операнда оператора присваивания.

· Для свойств список аргументов пуст при вызове метода доступа get и содержит выражение, указанное в качестве правого операнда оператора присваивания, при вызове метода доступа set.

· Для событий список аргументов состоит из выражения, указанного в качестве правого операнда оператора += или -=.

· В пользовательских операторах список аргументов состоит из одного операнда для унарного оператора и из двух операторов для бинарного оператора.

Аргументы свойств (§10.7), событий (§10.8) и пользовательских операторов (§10.10) всегда передаются как параметры значений (§10.6.1.1). Аргументы индексаторов (§10.9) всегда передаются как параметры значений (§10.6.1.1) или массивы параметров (§10.6.1.4). Для этих категорий функций-членов параметры ссылки и параметры вывода не поддерживаются.

Аргументы при вызове конструктора экземпляра, метода, индексатора или делегата указываются в виде списка аргументов:

argument-list:
argument
argument-list, argument

argument:
argument-nameopt argument-value

argument-name:
identifier:

argument-value:
expression
ref variable-reference
out variable-reference

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

Значение аргумента может иметь одну из следующих форм.

· Выражение, указывающее, что аргумент передается в виде параметра значения (§10.6.1.1).

· Ключевое слово ref, за которым следует ссылка на переменную (§5.4), указывающее, что аргумент передается в виде параметра ссылки (§10.6.1.2). Переменная должна быть определенно назначенной (§5.3) до того, как ее можно будет передать в качестве параметра по ссылке. Ключевое слово out, за которым следует ссылка на переменную (§5.4), указывающее, что аргумент передается в виде параметра вывода (§10.6.1.3). После вызова функции-члена, в котором переменная передается в виде параметра вывода, переменная считается явно присвоенной (§5.3).

Соответствующие параметры

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

Список параметров, использующийся в следующих случаях, определяется следующим образом:

· Для виртуальных методов, а также индексаторов, определенных в классах, список параметров выбирается из наиболее подходящего объявления или переопределения члена функции, начиная со статического типа получателя и выполняя поиск через его базовые классы.

· Для методов и индексаторов интерфейса список параметров выбирается из наиболее подходящего определения члена, начиная с типа интерфейса и выполняя поиск через базовые интерфейсы. Если список уникальных параметров не найден, создается список параметров с недоступными именами и без необязательных параметров; таким образом, при вызовах не смогут использоваться именованные параметры и пропускаться необязательные аргументы.

· Для разделяемых методов используется список параметров определяющего объявления разделяемого метода.

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

Положение аргумента или параметра определяется как число аргументов или параметров, предшествующих ему в списке аргументов или списке параметров.

Соответствующие параметры для аргументов членов функции устанавливаются следующим образом:

· Аргументы в списке аргументов конструкторов экземпляров, методов, индексаторов и делегатов:

o Позиционный аргумент, в котором фиксированный параметр встречается в той же позиции, что и в списке параметров, соответствует этому параметру.

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

o Позиционный аргумент члена функции, в котором массив параметров вызван в расширенной форме, а в соответствующей ему позиции в списке параметров нет фиксированного параметра, соответствует элементу в массиве параметров.

o Именованный аргумент соответствует параметру с тем же именем в списке параметров.

o Для индексаторов, при вызове метода доступа set выражение, указанное как правый операнд оператора назначения, соответствует неявному параметру value объявления метода доступа set.

· Для свойств при вызове метода доступа get аргументов нет. При вызове метода доступа set выражение, указанное как правый операнд оператора назначения, соответствует неявному параметру value объявления метода доступа set.

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

· Для пользовательских бинарных операторов левый операнд соответствует первому параметру, а правый - второму параметру объявления оператора.


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

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...

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



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

0.068 с.