Терминологические заморочки
В языке С, дедушке языка C#, все было очень просто: данные это числа, строки, массивы; программный код – операторы языка и функции. Функции в C, говоря языком структурного программирования, это подпрограммы.
С переходом от императивного языка C к объектно-ориентированному языку C++ понятие функции (как подпрограммы) сохранилось, однако каждая функция стала принадлежать какому-либо классу. Отметим что в С++ были добавлены специальные функции – конструкторы и деструкторы.
В язык C#, являющийся прямым наследником языка C++, многое перенесено без особых изменений, однако введенная терминология поначалу может ввести вас в заблуждение.
Разберемся с терминами и понятиями более подробно.
Оказывается, что к данным (данные-члены класса) теперь относятся не только поля, но и константы и события, а все, что содержит программный код, теперь называется функциями-членами класса, среди которых традиционная функция теперь называется методом класса.
Авторы языка определили, что функции-члены — это члены, которые обеспечивают некоторую функциональность для манипулирования данными класса. Они включают методы, свойства, конструкторы, финализаторы (деструкторы в С++), операции и индексаторы.
Для начинающего программиста важно освоить, прежде всего, работу с методами класса, а по сути (в прежнем понимании) – с функциями как подпрограммами. К этому добавим работу с конструкторами классов, а все остальное будет рассмотрено позже.
Шаблон объявления метода
[модификаторы] тип_возвращаемого_значения ИмяМетода([параметры])
{
// Тело метода
}
В C# определение метода состоит из указания модификаторов (static, public и т.п., модификаторы не обязательны), типа возвращаемого значения, имени метода и списка параметров в круглых скобках. Далее в фигурных скобках записывается тело метода.
Каждый параметр состоит из имени типа параметра и имени, по которому к нему можно обратиться в теле метода.
Возврат из метода и возврат значения
Если метод возвращает значение, то для указания точки выхода должен использоваться оператор возврата return вместе с возвращаемым значением. Если метод не возвращает ничего, то в качестве типа возврата указывается void (опустить тип возврата невозможно).
Если метод не принимает параметров, то все равно после имени метода должны присутствовать пустые круглые скобки (!!!). При этом включать в тело метода оператор возврата не обязательно — метод возвращает управление автоматически по достижении закрывающей фигурной скобки.
В целом, возврат из метода может произойти при двух условиях. Во-первых, когда встречается фигурная скобка, закрывающая тело метода. И во-вторых, когда выполняется оператор return. Имеются две формы оператора return: одна — для методов типа void (возврат из метода), т.е. тех методов, которые не возвращают значения, а другая — для методов, возвращающих конкретные значения.
Использование параметров
При вызове метода ему можно передать одно или несколько значений. Значение, передаваемое методу, называется аргументом. А переменная, получающая аргумент, называется формальным параметром, или просто параметром.
Параметры объявляются в скобках после имени метода. Синтаксис объявления параметров такой же, как и у переменных. А областью действия параметров является тело метода. За исключением особых случаев передачи аргументов методу, параметры действуют так же, как и любые другие переменные.
Два способа передачи параметров. В общем случае параметры могут передаваться методу либо по значению, либо по ссылке в зависимости от типа данных.
Если переменная, указанная в списке параметров, относится к типу значений (int, double, bool и т.п.), то вызываемый метод получает копию этой переменной, а это значит, что все изменения в ней, выполненные внутри метода будут утеряны.
Если переменная из списка параметров относится к ссылочному типу (например, массив), то параметр передается по ссылке, вызываемый метод получает саму переменную, поэтому любые изменения, которым она подвергнется внутри метода, останутся в силе после его завершения.
Поведение строк также отличается. Дело в том, что строки являются неизменными (изменение значения строки приводит к созданию совершенно новой строки), поэтому строки не демонстрируют поведение, характерное для ссылочных типов. Любые изменения, проведенные в строке внутри метода, не влияют на исходную строку.
Передача структуры (struct) как параметра через ее имя также произойдет через копирование (помните, структура относится к типу значений).
Если же для каких-либо типов данных необходима передача по ссылке (она более эффективна при большом объеме данных, который приходится копировать), то перед указанием типа параметра достаточно указать модификатор ref (reference – ссылка, англ.).
Рассмотрим три примера.
ПРИМЕР 1. В статье Первая программа на языке Си шарп мы разбирали программу:
using System; namespace Первая_программа { class Program { static void Main(string[] args) { Console.WriteLine("Привет, программист!"); Console.ReadKey(); } } }
В классе Program объявляется метод Main() (главная функция приложения), при выполнении которого вызываются два метода класса Console: WriteLine() (вывод строки текста) и ReadKey() (чтение символа с клавиатуры).
Ключевое слово static означает, что данный метод принадлежит классу Program.
Модификатор void указывает, что метод не возвращает никаких параметров.
Метод Main() в качестве списка параметров имеет массив строк. Отметим, что список параметров args в Main() пропустить. Метод WriteLine() имеет один параметр – строку, метод ReadKey() параметров не имеет.
ПРИМЕР 2. Объявление метода в примере Вычисление функции sin(x) выглядит так:
static double Sin2(double x) { double s = 0; // вычисления через ряд return s; }
Параметром (аргументом) функции объявляется переменная x типа double, метод возвращает результат также типа double (последний оператор метода return s;). Метод является статическим. Для вызова метода достаточно написать оператор y=Sin2(x);
ПРИМЕР 3. Передача параметров по значению, ссылке и через статическую переменную
Объявим в классе Program структуру West с двумя полями, статическую переменную f и метод vp( ):
static void vp(int[] b, West u, string t, double d, ref decimal y)
где b – массив, u – структура, t – строка, d – вещественное число, y – десятичный тип, передается по ссылке (модификатор ref).
В методе изменим эти переменные, а также и f для того, чтобы проверить способы передачи параметров (копированием или по ссылке).
Напечатаем эти значения до и после вызова метода vp().
Текст программы:
using System; namespace МетодыПередачаПараметров { class Program { struct West { public char c; public bool b; } static float f; static void Main(string[] args) { int []a=new int[3] {7,444,1}; double p = 3.14; decimal x=564.67M; West v; v.c = 'F'; v.b = false; string s = "Тест"; f = 6.28F; Console.WriteLine("{0} {1} {2} {3} {4} {5}", a[1], v.c, s, p, x, f); vp(a, v, s, p, ref x); Console.WriteLine("{0} {1} {2} {3} {4} {5}", a[1], v.c, s, p, x, f); Console.ReadKey(); } static void vp(int[] b, West u, string t, double d, ref decimal y) { b[1] = 555; d = 55; y = 76.465M; u.c = 'H'; t = "Проверка"; f = f / 2; } } }
Результат:
Обратите внимание, что второй элемент массива a[1], десятичное число x (передаваемое через ссылку — ref) и статическая переменная f изменились, а структура u, строка t и вещественное число d не изменились.
Отметим, что статическое поле f, объявленное в классе, доступно методам этого класса без механизма передачи параметров.
Некоторые итоги:
1) переменные, объявленные внутри метода или в списке его параметров, являются локальными переменными;
2) при вызове метода параметры из списка в заголовке метода либо копируются в локальные переменные метода, либо передаются по ссылке;
3) копируются все встроенные типы значений, структуры и (по сути) строки, хотя и они относятся к ссылочным типам;
4) по ссылке передаются массивы и другие объекты. Если их поля будут изменены внутри вызываемого метода, то эти изменения сохранятся при возврате в вызывающий метод;
5) передачу параметров по ссылке (без копирования в локальные переменные метода) можно обеспечить, используя модификатор ref. Однако это не имеет смысла для переменных ссылочного типа («масло масленое»);
6) нет необходимости передавать статические переменные класса через список параметров, в рамках одного класса они имеют смысл глобальных переменных в императивных языках программирования (хотя термин «глобальная переменная» в C# не употребляют);
7) для доступа к данным-членам и функциям-членам других классов необходимо указать имя класса, поставить точку, указать имя члена класса, например: Math.PI — константа, число пи=3,14158… , Math.Tan(x) — тангенс числа x, заданного в радианах;
8) доступ к членам других классов зависит от уровня его приватности (public, но не private или protected).
Как и во многих языках программирования для реализации рекурсивных алгоритмов в C# можно использовать рекурсивные методы.
Завершим раздел рассмотрением двух из трех ключевых принципов ООП — наследования и полиморфизма, считаю принцип инкапсуляции (объединение данных и и методов в класс) уже достаточно ясным.
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.
![]() |
![]() |
![]() |
![]() |
Текстовый материал хорошо всё объясняет.
Пример же с подобными именами переменных крайне сложен для чтения.
Грамматическая описка.
Пояснения к Примеру 1:
«Отметим, что список параметров args в Main() пропустить».
Скорее всего пропущено слово «можно»
Ух ты!
Можно разбираться.
А где список методов, которые как вы сказали, очень важны для обучения новичку?
Метод — это разновидность какого-либо действия любого класса, а не методов обучения новичков. Просто такая терминология. Перечитайте снова https://c-sharp.pro/?p=657 и взгляните на первую картинку, где метод — это член-функция класса. У каждого класса есть свой набор методов, например: класс Math содержит набор базовых математических функций (методы Sin(), Abs(), Exp() и т.д.). Чтобы их увидеть, воспользуйтесь интеллектуальной подсказкой — в коде программы запишите имя класса (Math) и поставьте точку. В выпадающем меню Вы увидите названия методов класса и еще двух констант. В классе Console Вы уже используете готовые методы ReadLine() и WriteLine(). Если Вы проектируете собственный класс, то его методы (действия) задайте самостоятельно.