С чего начинается выполнение выражения
Вычисление выражения начинается с выполнения операций высшего приоритета. Первым делом вычисляются выражения в круглых скобках - (expr), определяются значения полей объекта - x.y, вычисляются функции - f(x), переменные с индексами - a[i]. Выполнение этих операций достаточно понятно и не нуждается в комментировании. Операции checked и unchecked включают и выключают проверку преобразований арифметического типа в выражениях, которым они предшествуют. О других операциях этой категории скажу чуть подробнее.
Операции "увеличить" и "уменьшить" (increment, decrement)
Операции "увеличить на единицу" и "уменьшить на единицу" могут быть префиксными и постфиксными. К высшему приоритету относятся постфиксные операции x++ и x--. Префиксные операции имеют на единицу меньший приоритет. Главной особенностью как префиксных, так и постфиксных операций является побочный эффект, в результате которого значение x увеличивается (++) или уменьшается (--) на единицу. Для префиксных (++x, --x) операций результатом их выполнения является измененное значение x, постфиксные операции возвращают в качестве результата значение x до изменения. Приведу пример применения этих операций, дополнив метод Express новым фрагментом:
Обратите внимание, что хотя у постфиксной операции высший приоритет, это вовсе не означает, что при вычислении выражения вначале выполнится операция in1++, затем ++in1, и только потом будет проводиться сложение. Нет, вычисления проводятся в том порядке, в котором они написаны. Поскольку на входе значение in1 было равно 6, то выражение будет вычисляться следующим образом:
7(7) + 7 + 7(8),где в скобках записан побочный эффект операции. Так что консольный вывод даст следующий результат:
in1 = 21Операциями "увеличить" и "уменьшить" не следует злоупотреблять. Уже оператор, приведенный в нашем фрагменте, сложен для понимания из-за побочного эффекта. Понимаете ли вы, что при изменении порядка записи слагаемых, как это сделано в закомментированном операторе, результат вычисления выражения будет уже не 21, а 22?
Разный приоритет префиксных и постфиксных операций носит условный характер. Эти операции применимы только к переменным, свойствам и индексаторам класса, то есть к выражениям, которым отведена область памяти. В языках C++ и C# такие выражения называются l-value, поскольку они могут встречаться в левых частях оператора присваивания. Как следствие, запись в C# выражения < --x++ > приведет к ошибке. Едва лишь к x слева или справа приписана одна из операций, выражение перестает принадлежать к классу l-value выражений, и вторую операцию приписать уже нельзя.
6. Лекция: Выражения. Операции в выражениях 6.2
Операции sizeof и typeof
Операция sizeof возвращает размер значимых типов, заданный в байтах. Пояснения требуют некоторые особенности ее применения. Она должна выполняться только в небезопасных блоках. Поэтому проект, в котором она может использоваться, должен быть скомпилирован с включенным свойством /unsafe. На рис. 6.1 показано, как на странице свойств проекта можно включить это свойство:
Далее необходимо создать небезопасный блок, например, метод класса, помеченный как unsafe, в котором уже можно вызывать эту функцию (операцию). Приведу пример такого метода, созданного в классе Testing:
Рис. 6.1. Включение свойства /unsafe
В этом примере операция применяется к трем встроенным типам - bool, double, char. Консольный вывод дает в качестве результата значения: 1, 8 и 2. Обращаю внимание на то, что аргументом операции может быть только имя типа. Попытка применить эту операцию к переменной t типа Type, имеющей значение System.Int32, приводит к ошибке компиляции.
Операция typeof, примененная к своему аргументу, возвращает его тип. И здесь в роли аргумента может выступать имя класса, как встроенного, так и созданного пользователем. Возвращаемый операцией результат имеет тип Type. К экземпляру класса применять операцию нельзя, но зато для экземпляра можно вызвать метод GetType, наследуемый всеми классами, и получить тот же результат, что дает typeof с именем данного класса. Такой альтернативный способ получения типа по экземпляру класса int показан в приведенном выше программном фрагменте. А сейчас я приведу фрагмент, где используется вызов операции typeof:
t = typeof(Class1);Console.WriteLine("Тип класса Class1: {0}", t);t = typeof(Testing);Console.WriteLine("Тип класса Testing: {0}", t);