Метод — это блок кода, содержащий ряд инструкций. Программа инициирует выполнение инструкций, вызывая метод и указывая все аргументы, необходимые для этого метода. В C# все инструкции выполняются в контексте метода.
Метод Main является точкой входа для каждого приложения C# и вызывается общеязыковой средой выполнения (CLR) при запуске программы. В приложении, использующем инструкции верхнего уровня, метод Main создается компилятором и содержит все инструкции верхнего уровня.
В этой статье рассматриваются названные методы. Дополнительные сведения об анонимных функциях см. в статье Лямбда-выражения.
Сигнатуры методов
Методы объявляются в классе, структуре или интерфейсе путем указания уровня доступа, такого как public или private , необязательных модификаторов, таких как abstract или sealed , возвращаемого значения, имени метода и всех параметров этого метода. Все эти части вместе представляют собой сигнатуру метода.
Тип возврата метода не является частью сигнатуры метода в целях перегрузки метода. Однако он является частью сигнатуры метода при определении совместимости между делегатом и методом, который он указывает.
Как составлять комплексы для клиентов. Используемые методы ……. направленности методов ….
Параметры метода заключаются в скобки и разделяются запятыми. Пустые скобки указывают, что параметры методу не требуются. Этот класс содержит четыре метода:
abstract class Motorcycle < // Anyone can call this. public void StartEngine() // Only derived classes can call this. protected void AddGas(int gallons) < /* Method statements here */ >// Derived classes can override the base class implementation. public virtual int Drive(int miles, int speed) < /* Method statements here */ return 1; >// Derived classes must implement this. public abstract double GetTopSpeed(); >
Доступ к методу
Вызов метода в объекте аналогичен доступу к полю. После имени объекта добавьте точку, имя метода и круглые скобки. Аргументы перечисляются в этих скобках и разделяются запятыми. Таким образом, методы класса Motorcycle могут вызываться, как показано в следующем примере:
class TestMotorcycle : Motorcycle < public override double GetTopSpeed() < return 108.4; >static void Main() < TestMotorcycle moto = new TestMotorcycle(); moto.StartEngine(); moto.AddGas(15); moto.Drive(5, 20); double speed = moto.GetTopSpeed(); Console.WriteLine(«My top speed is «, speed); > >
Параметры и аргументы метода
Определение метода задает имена и типы всех необходимых параметров. Когда вызывающий код вызывает метод, он предоставляет конкретные значения, называемые аргументами, для каждого параметра. Аргументы должны быть совместимы с типом параметра, но имя аргумента (если есть), используемое в вызывающем коде, не обязательно должно совпадать с именем параметра, указанным в методе. Пример:
public void Caller() < int numA = 4; // Call with an int variable. int productA = Square(numA); int numB = 32; // Call with another int variable. int productB = Square(numB); // Call with an integer literal. int productC = Square(12); // Call with an expression that evaluates to int. productC = Square(productA * 3); >int Square(int i) < // Store input argument in a local variable. int input = i; return input * input; >
Передача по ссылке и передача по значению
По умолчанию при передаче в метод экземпляра типа значения вместо самого этого экземпляра передается его копия. Поэтому изменения в аргументе не оказывают влияния на исходный экземпляр в вызывающем методе. Чтобы передать экземпляр типа значения по ссылке, используйте ключевое слово ref . Дополнительные сведения см. в разделе Передача параметров типа значения.
Классификация методов научных исследований
При передаче в метод объекта ссылочного типа передается ссылка на этот объект. То есть метод получает не сам объект, а аргумент, который указывает расположение объекта. При изменении члена объекта с помощью этой ссылки это изменение отражается в аргументе в вызывающем методе, даже если объект передается по значению.
Ссылочный тип создается с помощью ключевого слова class , как показано в следующем примере.
public class SampleRefType
Теперь, если передать объект, основанный на этом типе, в метод, то будет передана ссылка на объект. В следующем примере объект типа SampleRefType передается в метод ModifyObject :
public static void TestRefType() < SampleRefType rt = new SampleRefType(); rt.value = 44; ModifyObject(rt); Console.WriteLine(rt.value); >static void ModifyObject(SampleRefType obj)
В этом примере, в сущности, делается то же, что и в предыдущем примере, — аргумент по значению передается в метод. Но поскольку здесь используется ссылочный тип, результат будет другим. В данном случае в методе ModifyObject изменено поле value параметра obj , а также изменено поле value аргумента, rt в методе TestRefType . В качестве выходных данных метод TestRefType отображает 33.
Дополнительные сведения о передаче ссылочных типов по ссылке и по значению см. в разделах Передача параметров ссылочного типа и Ссылочные типы.
Возвращаемые значения
Методы могут возвращать значение вызывающему объекту. Если тип возврата, указываемый перед именем метода, не void , этот метод может возвращать значение с помощью оператора return . Инструкция с ключевым словом return , за которым следует значение, соответствующее типу возврата, будет возвращать это значение объекту, вызвавшему метод.
Значение может быть возвращено вызывающей объекту по значению или по ссылке. Значения возвращаются вызывающему объекту по ссылке, если ключевое слово ref используется в сигнатуре метода и указывается после каждого ключевого слова return . Например, следующая сигнатура метода и оператор return указывают, что метод возвращает переменную с именем estDistance вызывающему объекту по ссылке.
public ref double GetEstimatedDistance()
Ключевое слове return также останавливает выполнение метода. Если тип возврата — void , инструкцию return без значения по-прежнему можно использовать для завершения выполнения метода. Без ключевого слова return этот метод будет останавливать выполнение при достижении конца блока кода.
Методы с типом возврата, отличным от void, должны использовать ключевое слово return для возврата значения. Например, в следующих двух методах ключевое слово return используется для возврата целочисленных значений.
class SimpleMath < public int AddTwoNumbers(int number1, int number2) < return number1 + number2; >public int SquareANumber(int number) < return number * number; >>
Чтобы использовать значение, возвращаемое из метода, вызывающий метод может применять сам вызов метода везде, где будет достаточно значения того же типа. Можно также назначить возвращаемое значение переменной. Например, следующие два примера кода достигают одной и той же цели.
int result = obj.AddTwoNumbers(1, 2); result = obj.SquareANumber(result); // The result is 9. Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2)); // The result is 9. Console.WriteLine(result);
Использование локальной переменной, в данном случае result , для сохранения значения является необязательным. Это может улучшить читаемость кода или может оказаться необходимым, если нужно сохранить исходное значение аргумента для всей области метода.
Чтобы использовать значение, возвращаемое по ссылке из метода, необходимо объявить локальную ссылочную переменную, если планируется изменение значения. Например, если метод Planet.GetEstimatedDistance возвращает значение Double по ссылке, можно определить его как локальную ссылочную переменную с использованием кода следующего вида:
ref double distance = ref Planet.GetEstimatedDistance();
Возвращать многомерный массив из метода M , который изменяет содержимое массива, необязательно, если вызывающая функция передает массив в M . В целях оптимизации можно возвращать полученный массив из M или функциональный поток значений, однако это необязательно. Это связано с тем, что C# передает все ссылочные типы по значению, а значение ссылки на массив представляет собой указатель на массив. В методе M любые изменения содержимого массива отслеживаются любым кодом, имеющим ссылку на массив, как показано в приведенном ниже примере:
static void Main(string[] args) < int[,] matrix = new int[2, 2]; FillMatrix(matrix); // matrix is now full of -1 >public static void FillMatrix(int[,] matrix) < for (int i = 0; i < matrix.GetLength(0); i++) < for (int j = 0; j < matrix.GetLength(1); j++) < matrix[i, j] = -1; >> >
Асинхронные методы
С помощью функции async можно вызывать асинхронные методы, не прибегая к использованию явных обратных вызовов или ручному разделению кода между несколькими методами или лямбда-выражениями.
Если пометить метод с помощью модификатора async , можно использовать в этом методе инструкцию await . Когда управление достигает выражения await в асинхронном методе, управление возвращается вызывающему объекту и выполнение метода приостанавливается до завершения выполнения ожидающей задачи. После завершения задачи можно возобновить выполнение в методе.
Асинхронный метод возвращается в вызывающий объект, когда он встречает первый ожидаемый объект, выполнение которого еще не завершено, или когда выполнение асинхронного метода доходит до конца — в зависимости от того, что происходит раньше.
В следующем примере метод Main служит примером асинхронного метода с типом возврата Task. Он переходит к методу DoSomethingAsync и, поскольку он выражается в одной строке, он может опустить ключевые слова async и await . Поскольку DoSomethingAsync является асинхронным методом, задача для вызова DoSomethingAsync должна быть ожидаемой, как показывает следующая инструкция: await DoSomethingAsync(); .
class Program < static Task Main() =>DoSomethingAsync(); static async Task DoSomethingAsync() < TaskdelayTask = DelayAsync(); int result = await delayTask; // The previous two statements may be combined into // the following statement. //int result = await DelayAsync(); Console.WriteLine($»Result: «); > static async Task DelayAsync() < await Task.Delay(100); return 5; >> // Example output: // Result: 5
Асинхронный метод не может объявить все параметры ref или out , но может вызывать методы, которые имеют такие параметры.
Определения текста выражений
Часто используются определения методов, которые просто немедленно возвращаются с результатом выражения или которые имеют единственную инструкцию в тексте метода. Для определения таких методов существует сокращенный синтаксис с использованием => :
public Point Move(int dx, int dy) => new Point(x + dx, y + dy); public void Print() => Console.WriteLine(First + » » + Last); // Works with operators, properties, and indexers too. public static Complex operator +(Complex a, Complex b) => a.Add(b); public string Name => First + » » + Last; public Customer this[long id] => store.LookupCustomer(id);
Если метод возвращает void или является асинхронным методом, то текст метода должен быть выражением инструкции (так же, как при использовании лямбда-выражений). Свойства и индексаторы должны быть только для чтения, и вы не должны использовать ключевое слово get метода доступа.
Iterators
Итератор выполняет настраиваемую итерацию по коллекции, например по списку или массиву. Итератор использует инструкцию yield return для возврата всех элементов по одному. При достижении инструкции yield return текущее расположение в коде запоминается. При следующем вызове итератора выполнение возобновляется с этого места.
Итератор вызывается из клиентского кода с помощью инструкции foreach .
Дополнительные сведения см. в разделе Итераторы.
Спецификация языка C#
Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.
См. также
- Руководство по программированию на C#
- Система типов C#
- Модификаторы доступа
- Статические классы и члены статических классов
- Наследование
- Абстрактные и запечатанные классы и члены классов
- params
- out
- ref
- Параметры методов
Источник: learn.microsoft.com
Методы используемые в программе
Если переменные хранят некоторые значения, то методы содержат собой набор инструкций, которые выполняют определенные действия. По сути метод — это именованный блок кода, который выполняет некоторые действия.
Общее определение методов выглядит следующим образом:
[модификаторы] тип_возвращаемого_значения название_метода ([параметры]) < // тело метода >
Модификаторы и параметры необязательны.
Ранее мы уже использовали как минимум один метод — Console.WriteLine() , который выводит информацию на консоль. Теперь рассмотрим, как мы можем создавать свои методы.
Определение метода
Определим один метод:
void SayHello()
Здесь определен метод SayHello , который выводит некоторое сообщение. К названиям методов предъявляются в принципе те же требования, что и к названиям переменных. Однако, как правило, названия методов начинаются с большой буквы.
Перед названием метода идет возвращаемый тип данных. Здесь это тип void , который указыает, что фактически ничего не возвращает, он просто производит некоторые действия.
После названия метода в скобках идет перечисление параметров. Но в данном случае скобки пустые, что означает, что метод не принимает никаких параметров.
После списка параметров в круглых скобках идет блок кода, который представляет набор выполняемых методом инструкций. В данном случае блок метода SayHello содержит только одну инструкцию, которая выводит строку на консоль:
Console.WriteLine(«Hello»);
Но если мы запустим данный проект, то мы не увидим никакой строки, которую должен выводить метод SayHello. Потому что после определения метод еще надо вызвать, чтобы он выполнил свою работу.
Вызов методов
Чтобы использовать метод SayHello, нам надо его вызвать. Для вызова метода указывается его имя, после которого в скобках идут значения для его параметров (если метод принимает параметры).
название_метода (значения_для_параметров_метода);
Например, вызов метода SayHello будет выглядеть следующим образом:
SayHello();
Поскольку метод не принимает никаких параметров, то после названия метода идут пустые скобки.
Объединим определение и вызов метода:
void SayHello() < Console.WriteLine(«Hello»); >SayHello(); // Hello SayHello(); // Hello
Консольный вывод программы:
Hello Hello
Преимуществом методов является то, что их можно повторно и многократно вызывать в различных частях программы. Например, в примере выше два раза вызывается метод SayHello.
При этом в данном случае нет разницы, сначала определяется метод, а потом вызывается или наоборот. Например, мы могли бы написать и так:
SayHello(); // Hello SayHello(); // Hello void SayHello()
Определим и вызовем еще несколько методов:
void SayHelloRu() < Console.WriteLine(«Привет»); >void SayHelloEn() < Console.WriteLine(«Hello»); >void SayHelloFr() < Console.WriteLine(«Salut»); >string language = «en»; switch (language)
Здесь определены три метода SayHelloRu() , SayHelloEn() и SayHelloFr() , которые также имеют тип void , не принимают никаких параметров и также выводит некоторую строку на консоль. Условно говоря, они выводят приветствие на определенном языке.
В конструкции switch проверяется значение переменной language , которая условно хранит код языка, и в зависимости от ее значения вызывается определенный метод. Так, в данном случае на консоль будет выведено
Hello
Сокращенная запись методов
Если метод в качестве тела определяет только одну инструкцию, то мы можем сократить определение метода. Например, допустим у нас есть метод:
void SayHello()
Методы
Фрагмент программного кода, к которому можно обратиться из другого места программы называется . Данный раздел описывает особенности описания и использования методов.
Общая информация
При разработке программы часто возникает необходимость повторного использования какого-либо ее фрагмента. Если нам нужно просто повторить этот фрагмент несколько раз — можно использовать цикл. А если этот фрагмент необходимо вызывать из разных мест программы — необходимо каким-то образом выделить программный код и оформить его специальным образом. Такой обособленный фрагмент кода называется . Метод всегда возвращает какое-либо значение. Подробнее о возвращаемом значении метода будет сказано далее.
Используемые определения
В процессе описания методов будут использоваться несколько терминов. Они уже могли использоваться и ранее в данном документе, но сейчас мы дадим им конкретные определения.
Определение метода
Прежде чем использовать метод, его надо определить. Определение метода выглядит следующим образом:
метод имя-метода([параметр[, параметр[, . ]]])[: описание-типа] тело-метода [[ значение]] ;
Каждый параметр описывается следующим образом:
имя-параметра: тип-параметра[ = значение-по-умолчанию]
имя-параметра задает имя параметра в соответствии со стандартными правилами формирования имен.
тип-параметра указывает, соответственно, тип параметра (в том числе и составной).
- Литералы (включая литералы коллекций) являются вычислимыми.
- Обращения к константам модулей являются вычислимыми.
- Операции над вычислимыми являются вычислимыми, кроме следующих исключений:
- Вызовы методов и обращения к свойствам.
- Вызовы конструкторов.
- Операции сложения значения типа Строка со значением другого типа.
Особенности передачи параметров
Переменные хранят ссылки на экземпляры. В методы передаются значения переменных. Таким образом можно в методе изменять состояние экземпляра, но нельзя изменить значение переменной, передаваемого в качестве аргумента метода.
метод Скрипт() пер ДляТеста = 5 Тестовый(ДляТеста) Консоль.Записать(«ДляТеста — topic/p p»>В данном примере, значение переменной ДляТеста в методе Скрипт() будет равно 5 и до вызова метода Тестовый() и после вызова этого метода. Такое поведение обеспечивает передача параметра «по значению».
Однако, если в метод передается экземпляр, который располагает методами для изменения своего содержимого, то ситуация будет немного другой. Рассмотрим пример:
метод Скрипт() пер ДляТеста = [1, 2] Тестовый(ДляТеста) Консоль.Записать(«ДляТеста — topic/p p»>В этом примере до выполнения метода Тестовый(), в массиве ДляТеста будет 2 значения: 1 и 2. После вызова метода Тестовый(), в массиве не будет ни одного элемента. В то же время, если в методе Тестовый() мы попробуем присвоить параметру Параметр1 какое-либо значение — это не приведет к каким-либо изменениям аргумента (переменной ДляТеста).
Вызов метода с именованными параметрами
При вызове метода допускается передача не только значений параметров в соответствии с их позицией в сигнатуре, то есть позиционных параметров, но и передача параметров вместе с их именами — именованных параметров. Например:
Перемножить(а = 2, б = 3)
ИмяМетода(ИмяПараметра1 = Значение, ИмяПараметра2 = Значение, . , ИмяПараметраN = Значение).
Примечание: Нумерация параметров в данном случае является условной, используется для отличия параметров друг от друга и не указывает на порядковый номер параметра при определении или при вызове метода.
Кроме того, в некоторых случаях данный способ параметризации имеет ряд преимуществ перед использованием позиционирования:
-
Передавать аргументы не обязательно в строгом порядке. Пользователю не требуется искать сигнатуру метода, чтобы вспомнить строгий порядок аргументов. Кроме того, если во время написания кода разработчик поменяет местами параметры в сигнатуре, в том числе параметры одного типа, это не приведет к ошибке во время компиляции или исполнения кода. Сравните:
метод Разделить(а: Число, б: Число): Число возврат а / б ; // Вызовы ниже равносильны: Разделить(3, 2) Разделить(а = 3, б = 2) Разделить(б = 2, а = 3)
метод РассчитатьСебестоимость(Цена: Число, Наценка: Число, Налог: Число): Число возврат Цена — (Цена * Наценка / 100 + Цена * Налог / 100) ; // Позиционные параметры РассчитатьСебестоимость(1, 10, 100) // Результат: -0.1.
Неправильно // Именованные параметры РассчитатьСебестоимость(Налог = 1, Наценка = 10, Цена = 100) // Результат: 89. Правильно
// Сигнатура метода метод ОтправитьСообщение(Сообщение: Строка, УдалитьПробелы: Булево, ОтправитьБезУведомления: Булево) // Позиционные параметры ОтправитьСообщение(» Привет, мир! «, Истина, Ложь) // Непонятно // Именованные параметры ОтправитьСообщение(» Привет, мир! «, УдалитьПробелы = Истина, ОтправитьБезУведомления = Ложь) // Понятно
метод РассчитатьСебестоимость(Налог: Число = 1, Наценка: Число = 10, Цена: Число): Число возврат Цена — (Цена * Наценка / 100 + Цена * Налог / 100) ; // Позиционные параметры РассчитатьСебестоимость(100) // Ошибка: Параметр «Цена» не имеет значения по умолчанию // Именованные параметры РассчитатьСебестоимость(Цена = 100) // Результат: 89. Правильно
При вызове метода можно смешивать позиционную и именованную формы параметризации. Например:
РассчитатьСебестоимость(Налог = 1, Наценка = 10, Цена = 100) РассчитатьСебестоимость(1, 10, Цена = 100)
- Если параметр со значением по умолчанию находится перед параметром с обязательным значением, то в вызове при опускании первого параметра требуется указать второй параметр в именованном виде.
- Параметры, имеющие значения по умолчанию, находящиеся в конце сигнатуры, можно опускать при вызовах.
При разрешении неоднозначности действуют следующие правила:
- Если под вызов в именованной форме подходит несколько методов, выдается ошибка неоднозначности.
- При объявлении методов проверка на возможную неоднозначность вызовов в именованной форме не производится, в отличие от позиционной.
- Некоторые перегрузки метода не допускают использования именованной формы:
метод ОтправитьСообщение(Сообщение: Строка, ДлинаСтроки: Число) ; метод ОтправитьСообщение(ДлинаСтроки: Число, Сообщение: Строка) ; ОтправитьСообщение(ДлинаСтроки = 255, Сообщение = » Привет, мир! «) // Ошибка неоднозначности
метод ОтправитьСообщение(ДлинаСтроки: Число, Сообщение = «Привет!», УдалитьПробелы = Истина) // Первая перегрузка ; метод ОтправитьСообщение(ДлинаСтроки: Число, УдалитьПробелы: Булево) // Вторая перегрузка ; // Какая перегрузка будет выбрана? ОтправитьСообщение(255) // Первая — у второй параметр УдалитьПробелы обязательный ОтправитьСообщение(255, Истина) // Вторая — используется позиционная форма вызова ОтправитьСообщение(255, » Привет, мир! «) // Первая — в сигнатуре второй перегрузки второй параметр имеет тип Булево, а не Строка ОтправитьСообщение(255, » Привет, мир! «, Истина) // Первая — только она имеет все три подходящих параметра ОтправитьСообщение(ДлинаСтроки = 255, УдалитьПробелы = Ложь) // Вторая — она короче, ошибки неоднозначности нет
Завершение метода и возвращаемое значение
Метод завершает свою работу после того, как завершается исполнение тела метода. Другим способом прервать исполнение метода является указание в необходимом месте метода ключевого слова возврат .
Если метод должен вернуть какое-либо значение, необходимо это значение указать в качестве параметра ключевого слова возврат . При этом тип фактически возвращаемого значения должен совпадать с типом возвращаемого значения, который указан при описании метода. Тип возвращаемого значения указывается после окончания списка формальных параметров метода. Тип указывается после символа «:» (двоеточие). Однако если метод, в котором нет ключевого слова возврат (или, другими словами, в котором не предполагается возвращаемого значения) будет использован в каком-то выражении или в качестве правого значения инструкции присваивания, то в качестве возвращаемого значения такого метода будет выступать значение Неопределено .
Повторное определение (перегрузка) методов
При разработке может возникнуть необходимость создать метод, который отличается количеством или типом параметров. При этом выполняемое действие существенно зависит от типа или количества параметров. Такое поведение можно реализовать двумя способами: составным типом параметров и значениями параметров по умолчанию или повторным определением метода.
Повторное определение метода заключается в том, что вы можете описать несколько методов с одним именем. Метод, который имеет несколько заголовков с разным составом параметров будет называться . При этом нужно помнить, что любой вызов перегруженного метода в исходном коде должен позволять компилятору однозначно определить, какой вариант метода необходимо использовать в данном случае. Если определить используемый вариант метода во время компиляции не представляется возможным, произойдет ошибка компиляции. Перегруженные методы не могут различаться только типом возвращаемого значения.
Рассмотрим примеры корректного и некорректного определения перегруженных методов:
1. метод Пример1(Параметр1: Строка|Число) 2. метод Пример1(Параметр1: Строка) 3. метод Пример1(Параметр1: Строка|Булево) 4. метод Пример2(Параметр1: Объект) 5. метод Пример2(Параметр1: Число) 6. метод Пример2(Параметр1: Число, Параметр2: неизвестно) 7. метод Пример3(Параметр1: Строка) 8. метод Пример3(Параметр1: Число) 9. метод Пример3(Параметр1: Строка, Параметр2: неизвестно = 22) 10. метод Пример4(Параметр1: Строка): Строка 11. метод Пример4(Параметр1: Число): Число 12. метод Пример4(Параметр1: Строка): Число
Метод Пример1() (строки 1, 2 и 3) нельзя переопределить предложенным способом. Текущее определение типов параметра метода не позволяет однозначно определить, какой вариант метода необходимо вызвать. Причина в том, что Параметр1 описан с использованием составного типа, при этом в каждом варианте метода присутствует тип Строка .
Метод Пример2() (строки 4, 5 и 6) можно описать, только исключив строку 5. Причиной является тот факт, что тип Объект является базовым для всех типов «1С:Исполнителя» . В то же время заголовок метода в строке 6 имеет другое количество параметров.
Метод Пример3() (строки 7, 8, 9) можно описать только исключив строку 9. Причиной является то, что второй параметр имеет значение по умолчанию, а следовательно, если указан один параметр (первый), компилятор не будет понимать, какой из вариантов метода использовать.
Наконец, метод Пример4() (строки 10, 11, 12) может быть описан или строками 10 и 11 или строками 11 и 12. Причиной является тот факт, что перегруженные методы не могут отличаться только типом возвращаемого значения. Поэтому вариант со строками 10 и 12 отпадает.
- Основное назначение перегрузки метода — это удобство разработчика.
- Если описываемый алгоритм изначально ориентирован на то, что в качестве параметров передаются составные типы, — не нужно выполнять перегрузку такого метода.
- Если алгоритм, описываемый методом, отличается от типа переданного параметра, то стоит рассмотреть возможность перегрузки метода, реализующего такой алгоритм.
- Перегруженными могут быть не только методы, но и конструкторы.
Источник: 1cmycloud.com