Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:
Область видимости, время жизни переменных, конфликты имен рассмотрены в лекции 5, семантика операторов — в лекции 8. Дополнительные сведения о семантике выполнения метода будут даны в этой лекции.
Знания семантики описаний и операторов достаточно для понимания семантики блока. Необходимые уточнения будут даны чуть позже.
Вызов метода. Синтаксис
Как уже отмечалось, метод может вызываться в выражениях или быть вызван как оператор. В качестве оператора может использоваться любой метод — как процедура, так и функция. Конечно, функцию разумно вызывать как оператор, только если она обладает побочным эффектом. В последнем случае она вызывается ради своего побочного эффекта, а возвращаемое значение никак не используется. Подобную
Если же попытаться вызвать процедуру в выражении, то это приведет к ошибке еще на этапе компиляции. Возвращаемое процедурой значение void несовместимо с выражениями. Так что в выражениях могут быть вызваны только функции.
Сам вызов метода, независимо от того, процедура это или функция, имеет один и тот же синтаксис:
имя_метода([список_фактических_аргументов])
Если это оператор, то вызов завершается точкой с запятой. Формальный аргумент, задаваемый при описании метода — это всегда имя аргумента (идентификатор). Фактический аргумент — это выражение, значительно более сложная синтаксическая конструкция. Вот точный синтаксис фактического аргумента:
[ref|out]выражение
О соответствии списков формальных и фактических аргументов
Между списком формальных и списком фактических аргументов должно выполняться определенное соответствие по числу, порядку следования, типу и статусу аргументов. Если в первом списке n формальных аргументов, то фактических аргументов должно быть не меньше n (соответствие по числу). Каждому i-му формальному аргументу (для всех i от 1 до n– i) ставится в соответствие i-й фактический аргумент. Последнему формальному аргументу, при условии, что он объявлен с ключевым словом params, ставятся в соответствие все оставшиеся фактические аргументы (соответствие по порядку).
Если формальный аргумент объявлен с ключевым словом ref или out, то фактический аргумент должен сопровождаться таким же ключевым словом в точке вызова (соответствие по статусу).
Появление ключевых слов при вызове методов — это особенность языка С#, отличающая его от большинства других языков. Такой синтаксис следует приветствовать, поскольку он направлен на повышение надежности программной системы, напоминая программисту о том, что данный фактический аргумент является выходным и значение его наверняка изменится после вызова метода. Однако из-за непривычности синтаксиса при вызове методов эти слова часто забывают писать, что приводит к появлению синтаксических ошибок.
Если формальный аргумент объявлен с типом T, то выражение, задающее фактический аргумент, должно быть согласовано по типу с типом T; допускает преобразование к типу T, совпадает с типом T или является его потомком (соответствие по типу).
Если формальный аргумент является выходным — объявлен с ключевым словом ref или out, — то соответствующий фактический аргумент не может быть выражением, поскольку используется в левой части оператора присваивания; следовательно, он должен быть именем, которому можно присвоить значение.
Вызов метода. Семантика
Что происходит в момент вызова метода? Выполнение начинается с вычисления фактических аргументов, которые, как мы знаем, являются выражениями. Вычисление этих выражений может приводить, в свою очередь, к вызову других методов, так что этот первый этап может быть довольно сложным и требовать больших временных затрат. В чисто функциональном программировании все вычисление по программе сводится к вызову одной функции, фактическими аргументами которой являются вызовы функций и так далее и так далее.
Для простоты
Семантика присваивания рассматривалась в лекциях 3, 6 и 7.
Каково следствие семантики вызова по значению! Если вы забыли указать ключевое слово ref или out для аргумента, фактически являющегося выходным, то к нему будет применяться вызов по значению. Даже если в теле метода происходит изменение значения этого аргумента, то оно действует только на время выполнения тела метода. Как только метод заканчивает свою работу (завершается блок), все локальные переменные (в том числе, созданные для замены формальных аргументов) оканчивают свое существование, так что изменения не затронут фактических аргументов и они сохранят свои значения, бывшие у них до вызова. Отсюда вывод: все выходные аргументы, значения которых предполагается изменить в процессе работы, должны иметь ключевое слово ref или out. Еще один важный вывод: ключевым словом ref полезно иногда снабжать и входные аргументы. Если известно, что фактический аргумент будет всегда представлен именем, а не сложным выражением, то в целях экономии памяти разумно для таких аргументов применять семантику вызова по ссылке. В этом случае не будет создаваться копия аргумента — это экономит память и время, что может быть важно при работе со сложными структурами.
Говоря о семантике вызова по ссылке и по значению, следует сделать одно важное уточнение. В объектном программировании, каковым является и программирование на С#, основную роль играют ссылочные типы — мы работаем с классами и объектами. Когда методу передается объект ссылочного типа, то все поля этого объекта могут меняться в методе самым беззастенчивым образом. И это несмотря на то, что объект формально не является выходным, не имеет ключевых слов ref или out, использует семантику вызова по значению. Сама ссылка на объект, как и положено, остается неизменной, но состояние объекта, его поля могут полностью обновиться. Такая ситуация типична и представляет один из основных способов изменения состояния объектов. Именно поэтому ref или out не часто появляются при описании аргументов метода.
Что нужно знать о методах?
Знания формального синтаксиса и семантики недостаточно, чтобы эффективно работать с методами. Рассмотрим сейчас несколько важных вопросов, касающихся различных сторон работы с методами класса.
Почему у методов мало аргументов?
Методы класса имеют значительно меньше аргументов, чем процедуры и функции в классическом процедурном стиле программирования, когда не используется концепция классов. За счет чего происходит уменьшение числа аргументов у методов? Ведь аргументы играют важную роль: они передают методу информацию, нужную ему для работы, и возвращают информацию — результаты работы метода — программе, вызвавшей его.