- •3. Лекция: Выражения и операции
- •Выражения
- •Приоритет и порядок выполнения операций
- •Перегрузка операций и методов
- •Преобразования типов
- •Организация программного проекта ConsoleExpressions
- •Операции высшего приоритета
- •Выражения в скобках
- •Операция индексации a[I, j]
- •Операция new
- •Операции sizeof и typeof
- •Операции "увеличить" и "уменьшить" (increment, decrement)
- •Унарные операции приоритета 1
- •Операция кастинга - приведения к типу
- •Проверяемые и непроверяемые блоки и выражения
- •Арифметические операции
- •Вычисление выражений
- •Память и время - два основных ресурса
- •Именованные константы
- •Операции отношения
- •Операции проверки типов
- •Операции сдвига
- •Логические операции
- •Логические операции над булевскими операндами
- •Логические операции над булевскими операндами и целыми числами. Работа со шкалами
- •Условное выражение
- •Операция присваивания
- •Операция ?? - новая операция c# 2.0
- •Лямбда-оператор - новая операция в c# 3.0
- •Преобразования внутри арифметического типа
- •Выражения над строками. Преобразования строк
- •Преобразования строкового типа в другие типы
- •Метод Parse
- •Преобразование в строковый тип
- •Класс Convert и его методы
- •Класс Console и его методы
- •Методы Read и ReadLine
- •Вывод данных на консоль. Методы Write и WriteLine
- •Вычисление выражений. Оценка времени вычислений
- •Геометрические фигуры
- •Преобразования типов
- •Проекты
-
Организация программного проекта ConsoleExpressions
Как обычно, все примеры программного кода, появляющиеся в тексте, являются частью программного проекта. Опишу структуру используемого в этой лекции консольного проекта, названного ConsoleExpressions. Помимо созданного по умолчанию класса Program, в проект добавлены два класса с именами TestingExpressions и Scales. Каждый из методов класса TestingExpressions представляет тест, который позволяет анализировать особенности операций, используемых при построении выражений, так что этот класс представляет собой сборник тестов. Класс Scale носит содержательный характер, демонстрируя работу со шкалами, о которых пойдет речь в этой лекции. Чтобы иметь возможность вызывать методы этих классов, в процедуре Main класса Program объявляются и создаются объекты этих классов. Затем эти объекты используются в качестве цели вызова соответствующих методов. Общая схема процедуры Main и вызова методов класса такова:
static void Main(string[] args)
{
string answer = "Да";
do
{
try
{
TestingExpressions test = new TestingExpressions();
test.Casting();
//Вызов других методов
…
}
catch (Exception e)
{
Console.WriteLine(
"Невозможно нормально продолжить работу!");
Console.WriteLine(e.Message);
}
Console.WriteLine("Продолжим работу? (Да/нет)");
answer = Console.ReadLine();
} while (answer == "Да" || answer == "да" || answer == "yes");
}
Всякий раз, когда в тексте лекции нужно будет привести пример кода, будет приводиться либо полный текст вызываемого метода, например, метода Casting, либо отдельный фрагмент метода.
-
Операции высшего приоритета
Рассмотрим подробнее операции из таблицы 3.1, отнесенные к высшему приоритету и выполняемые в первую очередь.
-
Выражения в скобках
Любое выражение, взятое в скобки, получает высший приоритет и должно быть вычислено, прежде чем к нему будут применимы какие-либо операции. Скобки позволяют изменить стандартный порядок вычисления выражения и установить порядок, необходимый для вычисления в данном конкретном случае. В сложных выражениях скобки полезно расставлять даже в том случае, если стандартный порядок совпадает с требуемым, поскольку наличие "лишних" скобок зачастую увеличивает наглядность записи выражения.
Вот классический пример выражения со скобками:
result = (x1 + x2) * (x1 - x2);
Понятно, что если убрать скобки, то первой выполняемой операцией будет операция умножения и результат вычислений будет совсем другим.
Поскольку согласно стандартному порядку выполняются вначале арифметические операции, потом операции отношения, а затем логические операции, то можно было бы не ставить скобки в следующем выражении:
bool temp = x1 + x2 > x1 - x2 && x1 - 2 < x2 + 1;
result = temp? 1 : 2;
Однако "лишние" скобки в записи выражения явно не помешают:
bool temp = ((x1 + x2) > (x1 - x2)) &&
((x1 - 2) < (x2 + 1));
result = temp? 1 : 2;
-
Операция вызова "точка" x.y, вызов функций F(x), вызов, инициируемый указателем x -> y
Несмотря на то, что точка - "малозаметный" символ, операция вызова x.y является одной из основных и важнейших операций в объектном программировании. Здесь x является целью вызова и представляет некоторый уже созданный объект, а y является свойством или методом этого объекта. Поскольку свойство объекта может задавать новый объект, может порождаться достаточно длинная цепочка вызовов (x.y1.y2.y3.y4), заканчивающаяся, как правило, терминальным свойством.
Если объект вызывает не свойство, а метод, то вызов метода сопровождается заданием фактических аргументов:
x.M(a1, … ak)
Когда такой вызов встречается в выражениях, метод должен возвращать значение, отличное от void (быть функцией), чтобы такое выражение могло быть использовано в качестве операнда какой-либо операции. Вызов метода, возвращающего значение void, используется как отдельный оператор, что неоднократно встречалось в наших примерах.
В качестве цели вызова может применяться не только имя объекта, но и имя класса. В этом случае вызывается статическое свойство или статический метод этого класса. Для каждого класса, у которого есть статические поля и статические методы, автоматически создается специальный объект (модуль), содержащий статические поля, к которым относятся и константы класса. Имя этого объекта совпадает с именем класса. Вот несколько примеров подобных вызовов:
Console.WriteLine(INPUT_FLOAT);
strInput = Console.ReadLine();
x1 = Convert.ToSingle(strInput);
Здесь в качестве цели вызовов выступают классы Console и Convert, вызывающие статические методы этих классов.
Если цель вызова указана, то такой вызов называется квалифицированным. Когда целью вызова является текущий объект, ее (цель) можно опускать, делая вызов неквалифицированным. Такой вызов всегда можно сделать квалифицированным, указав this в качестве имени текущего объекта:
result += this.n * this.m;
В данном случае можно было бы опустить имя текущего объекта и записать выражение следующим образом:
result += n * m;
Рассмотрим выражение:
result += x2 * x2 + F(x1) - x1 * x1;
Здесь все вызовы свойств x1, x2, метода F(x) записаны без квалификации, но можно превратить их в квалифицированные, показав явным образом, что реально при вычислении выражения используется операция вызова "точка". В последних примерах предполагается, что n, m, x1, x2 являются полями класса, а F - методом класса.
В неуправляемом коде, который появляется в блоках, объявленных как небезопасные, разрешена работа с указателями. Вызов полей и методов объекта, когда целью является указатель, задается операцией "стрелка" x -> y, где x - это указатель, а y - поле объекта, на который указывает указатель. Переходя от указателей к объекту, операцию "стрелка" можно заменить операцией "точка" следующим образом: (*x).y
В нашем курсе работа с указателями рассматриваться не будет.