Как мы знаем, класс обычно состоит из полей (данных) и методов по их обработке. Хотя мы уже использовали методы (например, метод Main()), сейчас рассмотрим этот вопрос подробнее.
Описание метода состоит из заголовка и тела этого метода. Формальная запись выглядит так:
метод_доступа тип_результата имя_метода(список_формальных_параметров)
{
// Тело метода.
// Состоит из описания локальных объектов и исполняемых операторов,
// с помощью которых реализуется алгоритм метода
}
Вызов метода в простейшем случае можно записать таким образом:
имя_метода(список_фактических_параметров);
Дадим уточнение к сказанному выше.
метод_доступа — это одно из ключевых слов (public, protected, private), определяющих доступность метода. Если это слово отсутствует при определении метода, то метод считается закрытым (private).
тип_результата — любой ранее известный тип данных (стандартный или пользовательский).
имя_метода — задаётся по общим правилам для записи идентификаторов.
список_формальных_параметров — это перечень записанных через запятую параметров, которые ожидаются в методе. Каждый из параметров в свою очередь записывается в виде:
тип_параметра имя_параметра
Перед типом могут задаваться дополнительные слова, уточняющие способ передачи данных в метод (это ref или out).
список_фактических_параметров — это те действительные данные, которые передаются в метод. Записываются через запятую без указания типа, но, возможно, со словами, уточняющими способ передачи данных.
Между списками фактических и формальных параметров должно быть полное соответствие по количеству и типу параметров, порядку их следования и способу передачи в метод.
Рассмотрим на простейшем примере то, как надо определять и использовать какой-либо метод.
Пример 1. Найти площадь прямоугольного треугольника, если заданы длины катетов этого треугольника.
Возможная реализация:
using System;
namespace Prim_Metod0
{
class Program
{
public static void Main(string[] args)
{
double a = 3, b = 4;
double s = Pl(a, b); // вызов метода
Console.WriteLine("s="+s);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
// Реализация метода
public static double Pl(double a, double b)
{
double s;
s = a * b / 2;
return s;
}
}
}
В этом примере в метод Pl() передаются два параметра типа double. Результат работы возвращается через имя метода и в вызывающем методе присваивается нужной переменной.
Метод Pl() вызывается в том же классе Program, в котором и был определён. Поэтому для вызова метода достаточно было упомянуть его имя со списком фактических параметров.
Если метод вызывается вне класса, где он определён, то для статического метода необходимо указывать перед именем метода ещё и имя класса, в котором определён этот метод.
Если метод обычный (не статический) и вызывается вне своего класса, то в других классах он может быть вызван только для объекта своего класса.
Пусть имеется класс Alfa с двумя методами: f() — обычный, fs() — статический. В методе fff() класса Beta необходимо вызвать эти методы. Вот как можно записать эти классы:
public class Alfa
{
public void f()
{
// тело метода
Console.WriteLine("Вызывается обычный метод f()");
}
public static void fs()
{
// тело метода
Console.WriteLine("Вызывается статический метод fs()");
}
}
public class Beta
{
// Метод класса Beta, в котором вызываем методы f() и fs() класса Alfa
public void fff()
{
// Создаём объект нужного класса:
Alfa x = new Alfa();
// Вызываем обычный метод:
x.f();
// А так вызываем статический метод:
Alfa.fs();
}
}
В C# в зависимости от ситуации можно передавать в метод параметры различными способами. Рассмотрим этот вопрос более подробно.
1.Передача данных по значению
Это основной способ передачи данных в метод, он действует по-умолчанию. При этом способе фактический параметр копируется в метод, и затем в этом методе работа ведётся с копией исходного фактического параметра. Поэтому параметр в методе может как угодно изменяться, но это ни как не отразится на значении фактического параметра после завершения работы с методом. Перед вызовом метода фактический параметр, передаваемый по значению, должен иметь какое-либо значение, т.е. быть проинициализирован.
В качестве параметра, передаваемого по значению, можно использовать константу, переменную или более сложное выражение соответствующего типа.
Данный способ передачи данных используется для тех из них, которые для метода являются только входными.
Для демонстрации передачи данных по значению приведём несложный пример.
Пример 2. Даны три действительных числа a, b и c. Определить: может ли существовать треугольник с такими длинами сторон.
Возможная реализация программы:
using System;
namespace Prim_Metod2
{
class Program
{
public static void Main(string[] args)
{
double a = 3, b = 4, c = 5;
Console.WriteLine("Длины сторон:\n a={0} b={1} c={2}", a, b, c);
if(Treug(a, b, c))
Console.WriteLine("Да, треугольник существует");
else
Console.WriteLine("Нет, треугольник не существует");
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static bool Treug(double a, double b, double c)
{
if(a + b > c && a + c > b && b + c > a)
return true;
else
return false;
}
}
}
В данном примере передаваемые по значению данные не изменялись в методе Treug(). Рассмотрим пример, когда данные меняются в методе.
Пример 3. Написать метод, который позволял бы произвести обмен значений двух переменных.
Возможная реализация:
using System;
namespace Prim_Metod3
{
class Program
{
public static void Main(string[] args)
{
int a = 3, b =4;
Console.WriteLine("До входа в метод:\n a={0} b={1}", a, b);
Obmen(a, b);
Console.WriteLine("После выхода из метода:\n a={0} b={1}", a, b);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static void Obmen(int a, int b)
{
Console.WriteLine("В методе до обмена:\n a={0} b={1}", a, b);
int c;
c = a;
a = b;
b = c;
Console.WriteLine("В методе после обмена:\n a={0} b={1}", a, b);
}
}
}
Результаты работы:
До входа в метод:
a=3 b=4
В методе до обмена:
a=3 b=4
В методе после обмена:
a=4 b=3
После выхода из метода:
a=3 b=4
Press any key to continue . . .
Как видно из листинга, параметры, передаваемые по значению, в методе изменялись, но на исходных данных это ни как не отразилось. Поэтому для задач, подобных данной, когда параметры должны стать изменёнными после выхода из метода, передача по значению не подходит. Необходимо использовать другие способы передачи данных в метод.
2.Передача параметров по ссылке
По примерам 1 и 2 этой темы мы знаем, что, если из метода необходимо вернуть одно значение, то это можно сделать через имя метода. Для возврата нескольких параметров этого недостаточно. Передача параметров по ссылке как раз и используется в том случае, когда из метода надо вернуть несколько значений.
Фактические параметры при передаче по ссылке перед обращением к методу обязательно должны иметь какие-либо начальные значения. После выхода из метода параметры могут иметь изменённые значение.
Для того, чтобы указать, что передача данных ведётся по ссылке, необходимо и при вызове метода, и в его определении параметры, передаваемые по ссылке, записывать со словом ref.
По ссылке можно передавать только переменные, но не константы и не выражения.
Этот метод хорош в том случае, когда параметры для решаемой задачи являются одновременно и входными, и выходными данными.
Рассмотрим снова задачу 3-го примера, только данные передадим по ссылке.
Пример 3а. Написать метод, который позволял бы произвести обмен значений двух переменных.
Возможная реализация:
using System;
namespace Prim_Metod3a
{
class Program
{
public static void Main(string[] args)
{
int a = 3, b =4;
Console.WriteLine("До входа в метод:\n a={0} b={1}", a, b);
Obmen(ref a, ref b);
Console.WriteLine("После выхода из метода:\n a={0} b={1}", a, b);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static void Obmen(ref int a, ref int b)
{
Console.WriteLine("В методе до обмена:\n a={0} b={1}", a, b);
int c;
c = a;
a = b;
b = c;
Console.WriteLine("В методе после обмена:\n a={0} b={1}", a, b);
}
}
}
Результаты работы:
До входа в метод:
a=3 b=4
В методе до обмена:
a=3 b=4
В методе после обмена:
a=4 b=3
После выхода из метода:
a=4 b=3
Press any key to continue . .
Как не трудно убедиться из результатов работы, теперь обмен данных, произведённый в методе, действительно отразился на переменных, передаваемых по ссылке. После выхода из метода они имеют новые (изменённые) значения.
3.Выходные данные
Надо заметить, что чаще всего результирующие параметры просто вычисляются в методе, а не являются одновременно и входными, и выходными данными. Для данных, которые являются только выходными, использование передачи по ссылке не слишком удобно, так как требует инициализации данных, которые мы только собираемся вычислять. В таких случаях выгоднее использовать так называемые «выходные данные». Для них вместо слова ref используют слово out. Эти данные реально так же передаются по ссылке, но для них не делается проверка на инициализацию до передачи в метод.
Пример4. Даны три числа. Вычислить их средние величины:
среднее арифметическое
среднее геометрическое
среднее квадратическое
Возможная реализация:
using System;
namespace Prim_Metod4
{
class Program
{
public static void Main(string[] args)
{
double a, b, c, ar, geo, kv;
Console.Write("a=");
a = double.Parse(Console.ReadLine());
Console.Write("b=");
b = double.Parse(Console.ReadLine());
Console.Write("c=");
c = double.Parse(Console.ReadLine());
Srednee(a, b, c, out ar, out geo, out kv);
Console.WriteLine("Среднее арифметическое = {0}",ar);
Console.WriteLine("Среднее геометрическое = {0}",geo);
Console.WriteLine("Среднее квадратическое = {0}",kv);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static void Srednee(double a, double b, double c,
out double ar, out double geo, out double kv)
{
ar = (a + b + c) / 3;
geo = Math.Pow(a * b * c, 1.0/3);
kv = Math.Sqrt(a * a + b * b + c * c);
}
}
}
4.Список параметров
В языке C# есть ещё один интересный вариант передачи данных: список параметров переменной длины. Такой список создаётся с использованием ключевого слова params.
Применение этого способа имеет ряд ограничений:
все параметры, входящие в список, должны быть одного типа и передаются они по значению (через такой список нельзя вернуть результат работы);
для одного метода можно использовать только один такой список, причем он должен находится в конце всего списка параметров.
Пример 5. Написать программу для вычисления суммы целых чисел. Суммирование оформим в виде метода. Обеспечим произвольное количество чисел для суммирования.
Возможная реализация:
using System;
namespace Prim_Metod5
{
class Program
{
public static void Main(string[] args)
{
int s;
s = fSum(4,3,12);
Console.WriteLine("Сумма = "+s);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static int fSum(params int [] x)
{
int s = 0;
for(int i = 0; i < x.Length; i++)
s += x[i];
return s;
}
}
}
В этом примере можно при вызове метода fSum() задать любое количество целых чисел, в том числе и не одного.
Приведём ещё один пример. В этом случае передадим в метод два параметра по значению и так же используем список параметров.
Пример 6. Найти сумму действительных чисел, которые попадают в отрезок [a, b].
Возможная реализация:
using System;
namespace Prim_Metod6
{
class Program
{
public static void Main(string[] args)
{
double s, a = 4.5, b = 11;
s = fSum(a, b, 4.6, 3, 12, 10);
Console.WriteLine("Сумма = "+s);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static double fSum(double a, double b, params double [] x)
{
double s = 0;
for(int i = 0; i < x.Length; i++)
if(x[i] >= a && x[i] <= b)
s += x[i];
return s;
}
}
}
|
|
|