- •1.2 Понятия приложения, проекта, решения
- •1.3 Среда разработки Visual Studio .Net
- •1.4 Создание первого проекта
- •1. 5 Компиляция и выполнение программы в среде clr
- •2.1 Основы технологии ооп
- •2.2 Состав языка
- •2.3 Типы данных
- •2.4 Переменные и константы
- •2.5 Организация ввода-вывода данных. Форматирование
- •3.1 Некоторые операции с#
- •Отрицание:
- •Условная операция.
- •3.2 Выражения и преобразование типов
- •3.3 Перечень операций
- •3.4 Математические функции языка с#
- •4.1 Операторы следования
- •4.2 Операторы ветвления
- •4.3 Операторы цикла
- •4.4 Операторы безусловного перехода
- •5.1 Методы: основные понятия
- •5.2 Перегрузка методов
- •6.1 Прямая рекурсия
- •6.2 Косвенная рекурсия
- •7.1 Оператор try
- •7.2 Операторы checked и unchecked
- •7.3 Генерация собственных исключений
- •7.4 Приемы использования обработчиков исключений
- •8.1 Одномерные массивы
- •8.2 Массив как параметр
- •8.3 Массив как объект
- •8.4 Многомерные массивы
- •8.5 Ступенчатые массивы
- •8.6 Оператор foreach и его использование при работе с массивами
- •Примеры
- •9.1 Символы char
- •9.2 Неизменяемые строки string
- •9.3 Изменяемые строки
- •Вариант 1
- •Вариант 2
- •Редактирование текста;
- •10.1 Метасимволы в регулярных выражениях
- •10.2 Поиск в тексте по шаблону
- •10.3 Редактирование текста
- •11.1 Байтовый поток
- •11.2 Символьный поток
- •11.3 Двоичные потоки
- •11.4 Перенаправление стандартных потоков
- •Практикум
- •12.1.Работа с файловой системой: классы Directory и Filе и классы DirectoryInfo и FileInfo
- •12.2 Класс FileSystemInfo
- •12.3 Класс DirectoryInfo
- •12.4 Класс Directory
- •2. Реализуем метод, позволяющий получить по имени узла полное имя соответствующей папки
- •12.2 Работа с файлами
- •12.5 Класс File
- •13.1. Классы: основные понятия, данные, методы, конструкторы, свойства
- •13.2 Данные: поля и константы
- •13.3 Методы
- •Конструкторы экземпляра
- •13.4 Конструкторы класса
- •13.5 Свойства
- •13.6 Один класс - один файл
- •13.7. Классы: деструкторы, индексаторы Деструкторы
- •Индексаторы
- •13.8 Операции класса
- •14.1 Иерархия и наследование
- •Использование защищенного доступа
- •14.2 Наследование конструкторов
- •Позволяет вызвать конструктор базового класса:
- •Позволяет получить доступ к члену базового класса, который скрыт "за" членом производного класса.
- •14.3 Многоуровневая иерархия
- •14.4 Переменные базового класса и производного класса
- •14.5 Виртуальные методы
- •14.6 Абстрактные методы и классы
- •14.7 Запрет наследования
- •Самостоятельная работа
- •15.1. Пользовательские и стандартные интерфейсы
- •15.2 Стандартные интерфейсы .Net
- •15.3 Структуры
- •Задание
- •16.1. Классификация коллекций.
- •16.2 Коллекции общего назначения
- •16.3 Класс Stack
- •16.4 Класс Queue
- •16.5 Класс ArrayList
- •16.6 Класс Hashtable
- •17.1 Струткура простейшего windows-приложения
- •17.2 Элементы управления на форме
- •17.3 Обработка событий
- •17.4 Работа с элементами управления
- •17.5 Кнопки
- •17.6 Работа с элементами управления в режиме работы приложения
- •17.7 Работа со списками: ListBox, ComboBox, NumericUpDown.
- •17.8 Работа с переключателями: RadioButton, CheckBox
- •18.1 Рисование в форме
- •18.2 Работа с изображениями
5.2 Перегрузка методов
Иногда бывает удобно, чтобы методы, реализующие один и тот же алгоритм для различных типов данных, имели одно и то же имя. Использование нескольких методов с одним и тем же именем, но различными типами и количеством параметров называется перегрузкой методов. Компилятор определяет, какой именно метод требуется вызвать, по типу и количеству фактических параметров.
Рассмотрим следующий пример:
class Program
{
static int max(int a) //первая версия метода max
{
int b = 0;
while (a > 0)
{
if (a % 10 > b) b = a % 10;
a /= 10;
}
return b;
}
static int max(int a, int b) //вторая версия метода max
{
if (a > b) return a;
else return b;
}
static int max(int a, int b, int c) //третья версия метода max
{
if (a > b && a > c) return a;
else if (b > c) return b;
else return c;
}
static void Main()
{
int a = 1283, b = 45, c = 35740;
Console.WriteLine(max(a));
Console.WriteLine(max(a, b));
Console.WriteLine(max(a, b, c));
}
}
При вызове метода max компилятор выбирает вариант, соответствующий типу и количеству передаваемых в метод аргументов. Если точного соответствия не найдено, выполняются неявные преобразования типов в соответствии с общими правилами. Если преобразование невозможно, выдается сообщение об ошибке. Если выбор перегруженного метода возможен более чем одним способом, то выбирается "лучший" из вариантов (вариант, содержащий меньшие количество и длину преобразований в соответствии с правилами преобразования типов). Если существует несколько вариантов, из которых невозможно выбрать лучший, выдается сообщение об ошибке.
Перегрузка методов является проявлением полиморфизма, одного из основных свойств ООП. Программисту гораздо удобнее помнить одно имя метода и использовать его для работы с различными типами данных, а решение о том, какой вариант метода вызвать, возложить на компилятор. Этот принцип широко используется в классах библиотеки .NET. Например, в стандартном классе Console метод WriteLine перегружен 19 раз для вывода величин разных типов.
Практикум
-
Разработать метод для нахождения минимального из двух чисел. Вычислить с помощью него значение выражения .
Пример.
using System;
namespace Hello
{
class Program
{
static double min(double a, double b)
{
return (a < b) ? a : b;
}
static void Main(string[] args)
{
Console.Write("x=");
double x = double.Parse(Console.ReadLine());
Console.Write("y=");
double y = double.Parse(Console.ReadLine());
double z = min(3 * x, 2 * y) + min(x - y, x + y);
Console.WriteLine("z=" + z);
}
}
}
-
Постройте таблицу значений функции для с шагом .
Замечание. Для решения задачи использовать вспомогательный метод.
Пример:
using System;
namespace Hello
{
class Program
{
static double f (double x)
{
double y;
if (x >= 0.9) y = 1 / Math.Pow(1 + x, 2);
else if (x >= 0) y = 0.2 * x + 0.1;
else y = x * x + 0.2;
return y;
}
static void Main(string[] args)
{
Console.Write("a=");
double a = double.Parse(Console.ReadLine());
Console.Write("b=");
double b = double.Parse(Console.ReadLine());
Console.Write("h=");
double h = double.Parse(Console.ReadLine());
for (double i = a; i <= b; i += h)
Console.WriteLine("f({0:f2})={1:f4}", i, f(i));
}
}
}
-
Перегрузите метод из предыдущего раздела так, чтобы его сигнатура (заголовок) соответствовала виду static void f (double x, out double y). Продемонстрируйте работу перегруженных методов.
Самостоятельная работа
Теоретический материал
Пусть a1, a2, …, an - произвольная числовая последовательность. Рекуррентным соотношением называется такое соотношение между членами последовательности, в котором каждый следующий член выражается через несколько предыдущих, т.е ak = f(ak-1, ak-2, …, ak-l, l < k (1).
Последовательность задана рекуррентно, если для нее определено рекуррентное соотношение вида (1) и заданы первые l ее членов.
Самым простым примером рекуррентной последовательности является арифметическая прогрессия. Рекуррентное соотношение для нее записывается в виде: ak = ak-1 + d, где d - разность прогрессии. Зная первый элемент и разность прогрессии, и, используя данное рекуррентное соотношение, можно последовательно вычислить все остальные члены прогрессии.
Рассмотрим пример программы, в которой вычисляются первые n членов арифметической прогрессии при условии, что a1=1/2 и d=1/4.
static void Main()
{
Console.Write("a=");
double a = double.Parse(Console.ReadLine());
Console.Write("h=");
double d = double.Parse(Console.ReadLine());
Console.Write("n=");
int d = int.Parse(Console.ReadLine());
Console.WriteLine("a1="+ a); //вывели первый член последовательности
//организуем вычисление 2, 3, … ,n члена последовательности
for (int i = 2; i <= n; ++i)
{
a += d; //для этого прибавляем к предыдущему члену значение d
Console.WriteLine("a{0}={1}", i, a); //и выводим новое значение а на экран
}
}
Результат работы программы:
n состояние экрана
5
a1: 0.5
a2: 0.75
a3: 1.
a4: 1.25
a5: 1.5
Более сложная зависимость представлена в последовательности Фибоначчи: a1 = a2= 1, an = an-1 + an-2. В этом случае каждый член последовательности зависит от значений двух предыдущих членов. Рассмотрим пример программы, в которой вычисляются первые n членов последовательности Фибоначчи.
static void Main()
{//задали известные члены последовательности
int a1=1, a2=1, a3;
Console.Write("n=");
int n = int.Parse(Console.ReadLine());
//вывели известные члены последовательности
Console.WriteLine("a1={0}\na2={1}",a1,a2);
/*Организуем цикл для вычисления членов последовательности с номерами 3 4…n.
При этом в переменной a1 будет храниться значение члена последовательности с номером i-2,в переменной a2 - члена с номером i-1, переменная а будет использоваться для вычисления члена с номером i. */
for (int i = 3; i <= n; ++i)
{
//по рекуррентному соотношению вычисляем член последовательности с номером i //и выводим его значение на экран
a3=a1+a2;
Console.WriteLine("a{0}={1}", i, a3);
//выполняем рекуррентный пересчет для следующего шага цикла
a1 = a2; //в элемент с номером i-2 записываем значение элемента с номером i-1
a2 = a3; //в элемент с номером i-1 записываем значение элемента с номером i
}
}
Результат работы программы:
n состояние экрана
5 a1: 1
a2: 1
a3: 2
a4: 3
a5: 5
Лекция 6. Рекурсивные методы