
- •Язык c# и структура простой программы
- •Что такое .Net Framework
- •Что такое с#
- •Создание первой программы на с#
- •Пространство имен System
- •С# как язык Объектно-Ориентированного Программирования (ооп)
- •Состав и назначение файлов проекта
- •Структура сборки
- •Элементы языка c#
- •Базовый синтаксис с#
- •Переменные
- •Числа без знака
- •Числа со знаком
- •Числа для финансистов
- •Текстовые символы
- •Логический тип данных
- •Литералы с плавающей точкой
- •Символьные литералы
- •Строковые литералы
- •Выражения и операторы с#
- •Инициализация переменных и оператор присваивания
- •Значение в левой части
- •Ввод данных с консоли
- •Математические операторы
- •Вычисление остатка при целочисленном делении
- •Унарные операторы
- •Унарное логическое отрицание
- •Составные операторы
- •Поразрядные операторы
- •Поразрядное логическое и
- •Поразрядное логическое или
- •Поразрядное логическое исключающее или
- •Унарная поразрядная операция дополнения
- •Поразрядный сдвиг
- •Пример использования поразрядных операторов
- •Логические операторы
- •Операторы отношения
- •Приоритеты операторов
- •Исполнители алгоритмов
- •Исполнитель Чертежник
- •Исполнитель Робот
- •Компьютер как формальный исполнитель алгоритмов
- •Блок-схема
- •Псевдокод
- •Необходимые свойства алгоритма
- •Понятие о временной сложности алгоритма
- •Примеры
- •Правила для определения сложности
- •Тернарный условный оператор
- •Применение логических операций
- •Конструкция выбора
- •Примеры применения оператора выбора
- •Объединение меток case
- •Пропущенный break
- •Пример программы: Простые числа
- •Пример обработки одномерного массива чисел
- •Использование генератора случайных данных
- •Использование оператора foreach
- •Типы задач обработки одномерных числовых массивов
- •Поиск элемента в массиве
- •Многомерные массивы
- •Базовые операции со строками
- •Методы типа string
- •Копирование и клонирование строк
- •Конкатенация строк
- •Извлечение подстроки
- •Вставка подстроки
- •Замена символов и строк
- •Удаление символов из строки
- •Удаление незначащих пробелов
- •Преобразование к верхнему и нижнему регистру
- •Выравнивание по левому и правому краю поля
- •Объединение массива строк
- •Разбор строки
- •Сравнение строк
- •Форматирование текстовых строк
- •Функции
- •Описание и использование функций
- •Возвращаемые значения
- •Передача параметров
- •Выходные параметры
- •Область действия переменных
- •Область действия переменных и управляющие конструкции
- •Рекурсия
- •Параметры функции Main()
- •Перегрузка функций
- •Перечислимый тип
- •Определение перечислимых типов
- •Структуры
- •Описание структур
- •Использование структур в качестве параметров функций
- •Использование структур в качестве возвращаемых значений функций
- •Функции структур
- •Файлы и потоки
- •Основные классы ввода и вывода
- •Классы для работы с потоками
- •Классы для работы с потоками текстовых символов
- •Работа с текстовыми файлами
- •Запись двоичных данных
- •Пример программы для работы с двоичным файлом
- •Просмотр содержимого каталога
- •Получение информации о каталоге
Передача параметров
Функции без параметров встречаются не так уж часто. Причина здесь в том, что наличие параметров позволяет передавать при вызове одной и той же функции различные данные для обработки, что существенно увеличивает область применения и полезность такой функции.
Если функция должна получать параметры, то необходимо задать:
Список принимаемых функцией параметров в ее описании, а также тип каждого параметра;
Совпадающий по количеству значений список параметров при каждом вызове функции.
Это предполагает использование следующего кода:
static <возвращаемыйТип> <имяФункции>{<типПараметра> <имяПараметра>, . . . )
{
...
return <возвращаемоеЗначение>;
}
Здесь может быть произвольное число параметров, для каждого из которых указываются тип и имя. В качестве разделителя между параметрами используются запятые. Каждый из параметров доступен внутри данной функции в качестве переменной.
Например, следующая простая функция принимает два параметра типа double и возвращает их произведение:
static double product (double param1, double param2)
{
return param1 * param2;
}
Следующая функция принимает в качестве параметра массив целых чисел и возвращает наибольшее из них. Ее описание имеет следующий вид:
static int maxValue(int[] intArray)
{
int maxVal = intArray[0];
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal)
maxVal = intArray[i];
}
return maxVal;
}
Данная функция — maxValue() —имеет один параметр, который описан как массив типа int с именем intArray. Возвращаемое значение также имеет тип int.
Определение максимального значения представляет собой несложную задачу и выполняется за один цикл. Когда выполнение цикла завершено, переменная maxVal содержит наибольшее значение данного массива, которое и возвращается оператором return.
Код, расположенный в Main(), объявляет и инициализирует простой целый массив, который будет использоваться совместно с функцией maxValue():
int[] myArray = {1, 8, 3, 6, 2, 5, 9, 3, 0, 2};
При вызове функции maxValue() значение присваивается переменной maxVal типа int:
int maxVal = maxValue(myArray);
Полученное значение можно вывести на экран с помощью Console.WriteLine() или использовать каким-либо иным способом:
Console.WriteLine("Максимум в массиве myArray равен {0}", maxVal);
Вся программа будет иметь вид:
using System;
namespace Function2
{
class Program
{
static void Main(string[] args)
{
int[] myArray = { -1, 8, 3, 6, 2, 5, -9, 3, 0, 2 };
int maxVal = maxValue(myArray);
Console.WriteLine("Максимум в массиве myArray равен {0}",
maxVal);
Console.ReadLine();
}
static int maxValue(int[] intArray)
{
int maxVal = intArray[0];
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal)
maxVal = intArray[i];
}
return maxVal;
}
}
}
Как видно из листинга, порядок появления функций в программе может быть любым, главное – чтобы все они были определены. Так как точкой входа в программу является функция Main(), то логично поставить ее на первое место, а затем определить все вызываемые из нее функции. В этом случае при просмотре текста программы от начала к концу файла легче понять, что выполняет данная программа (при просмотре кода Main()), а затем – как это происходит (при просмотре).
Массивы параметров
В С# предусмотрена возможность задания одного (и только одного) специального параметра функции. Этот параметр, который обязательно должен располагаться последним, известен под названием массива параметров. Он позволяет при обращении к функциям использовать переменное количество параметров. Массив параметров описывается посредством ключевого слова params.
Передача параметров по ссылке и по значению
Во всех предыдущих функциях применялись параметры, передаваемые по значению. Другими словами, мы передавали значение в переменную, которая затем использовалась внутри функции. Любые изменения, которые эта переменная претерпевала внутри функции, не оказывали никакого влияния на параметр, использованный при вызове функции. В качестве примера рассмотрим функцию, которая удваивает передаваемый ей параметр и выводит результат на экран:
static void showDouble(int val)
{
val *= 2;
Console.WriteLine("Удвоенное значение val = {0}", val) ;
}
В этой функции происходит удвоение передаваемого параметра. Если мы вызовем эту функцию из Main() следующим образом:
int myNumber = 5;
Console.WriteLine("До вызова функции myNumber = {0}", myNumber);
showDouble(myNumber);
Console.WriteLine("После вызова функции myNumber = {0}", myNumber);
Результат работы программы будет таким:
Таким образом, вызов функции showDoubl() с переменной myNumber в качестве параметра не оказывает никакого влияния на переменную myNumber, описанную в Main(), несмотря на то, что параметр, которому присваивается ее значение, удваивается.
Это достаточно удобно, если мы не хотим, чтобы значение передаваемого параметра изменялось после вызова функции. Но если мы пожелаем, чтобы значение переменной myNumber было изменено, возникнет проблема.
Можно воспользоваться функцией, которая возвращает новое значение переменной myNumber, и вызвать ее следующим образом:
int myNumber = 5;
Console.WriteLine("До вызова функции myNumber = {0}", myNumber);
myNumber = showDouble(myNumber);
Console.WriteLine("После вызова функции myNumber = {0}", myNumber);
При анализе данного кода можно понять, что переменная myNumber получает новое значение; к сожалению, такой способ не позволяет вернуть изменения значений нескольких переменных, используемых в качестве параметров (поскольку функции всегда возвращают только одно значение).
Вместо этого следует передавать параметр по ссылке. Это означает, что функция будет работать именно с той переменной, которая использовалась при вызове функции, а не с переменной, которая имеет то же значение. Следовательно, любые изменения переменной, использованной внутри функции, отразятся на значении переменной, использовавшейся в качестве параметра. Для этого при описании параметра необходимо воспользоваться ключевым словом ref:
static void showDouble(ref int val)
{
val *= 2;
Console.WriteLine("Удвоенное значение val = {0}", val);
}
Вторично ключевое слово ref необходимо использовать при вызове функции (это обязательное требование, поскольку тот факт, что параметр передается по ссылке, является неотъемлемой частью описания этого параметра):
int myNumber = 5;
Console.WriteLine("До вызова функции myNumber = {0}", myNumber);
showDouble(ref myNumber);
Console.WriteLine("После вызова функции myNumber = {0}", myNumber);
В этом случае на консоль будет выведен следующий текст:
Для переменных, используемых в качестве параметров типа ref, имеются два ограничения. Во-первых, поскольку существует вероятность, что в результате вызова функции значение вызываемого по ссылке параметра будет изменено, то при вызове функции запрещается использовать переменные типа const. Отсюда следует, что следующий вызов является недопустимым:
const int myNumber = 5;
Console.WriteLine("До вызова функции myNumber = {0}", myNumber);
showDouble(ref myNumber);
Console.WriteLine("После вызова функции myNumber = {0}", myNumber);
Во-вторых, необходимо использовать заранее инициализированную переменную. С# не гарантирует, что параметр типа ref будет инициализирован той функцией, в которой он используется. Следующий код также является недопустимым:
int myNumber;
showDouble(ref myNumber);
Console.WriteLine("После вызова функции myNumber = {0}", myNumber);