Использование параметров и возвращаемых значений
Функции
Функции представляют собой блоки кода, позволяющие выполнять одни и те же операции над различными значениями данных. Функции определяются один раз и могут вызываться из любой точки приложения.
Определение функции состоит из следующих элементов:
- Два ключевых слова: static и типа возвращаемого значения (void, если ничего не возвращает).
- Имя функции, за которым следуют круглые скобки, внутри которых размещаются параметры.
- Заключенный в фигурные скобки блок кода, который подлежит выполнению.
Параметры в определении функции обычно называют формальными. Их имена используются в коде функции. При вызове функции на место формальных параметров подставляются их значения (фактические параметры), которые должны указываться точно так, как в определении функции, т.е. в соответствующем количестве и порядке.
Параметры, передаваемые функции, могут быть трех видов: параметры-значения, параметры-ссылки и выходные параметры.
При использовании параметра-значения в функцию передается копия значения переменной из вызывающей функции и ее изменение в функции не изменяет значение переменной в вызывающей функции.
При использовании параметров-ссылок и выходных параметров в функцию передается адрес переменной из вызывающей функции, что дает ей возможность доступа к самой переменной. Параметры-ссылки и выходные параметры используют модификаторы ref и out перед параметром как в определении, так и в вызове функции.
Существуют два важных отличия:
- В качестве параметра ref применять неинициализированную переменную нельзя, а в качестве out – можно.
- Параметр out должен трактоваться функцией, которая его использует, как не имеющий присвоенного значения.
Преимущества использования функций по сравнению с многократным использованием повторяющегося кода:
- Так как код функции хранится в одном месте памяти, это существенно упрощает внесение в него изменений и позволяет при этом избежать множества возможных ошибок.
- Код приложения сокращается за счет группировки внутренних действий и становится удобочитаемым.
Предлагаемое рассмотрение функций охватывает следующие ключевые моменты:
- Определение и использование функций в консольных приложениях.
- Обмен данными с функциями через возвращаемые значения, параметры и глобальные переменные. Передача параметров по ссылке и по значению.
- Использование параметров командной строки функции main().
- Перегрузка функций.
Любой проект консольного или оконного типа должен иметь по крайней мере одну точку входа, определяемую статической функцией Main(). Каждая функция, в том числе и функция Main(), должна принадлежать какому-нибудь классу, т.е. быть методом. Функция Main() объявляется как статический метод, не требующий создания экземпляра (Instance) класса для ее вызова. (Внимание! В приложении, имеющем несколько классов, функция Main() может входить в несколько из них. В этом случае для определения единственной точки входа нужно определить через окно свойств проекта, какой именно класс будет стартовым для данного приложения.)
Обмен данными с функциями через возвращаемые значения, параметры и глобальные переменные.
Глобальные переменные
Скомпилируйте и выполните (по очереди) все фрагменты программ Пример 1 и Пример 2 (включая закомментированные) и объясните результаты.
Пример 1.
//Область видимости переменных в функциях
using System;
namespace Func01
{
class Program
{
/* static void Write()
{
Console.WriteLine("myString = {0}",myString);//ошибка
}
static void Main(string[] args)
{
string myString = "String defined in Main()");//не используется
Write();
Console.ReadKey();
}
*/
//описать последовательность выполнения операторов
/* static void Write()
{
string myString = "строка из Write()";//локальная
Console.WriteLine("\n это Write()!");
Console.WriteLine("myString = {0}", myString);
}
static void Main(string[] args)
{
string myString = "строка из Main()";//локальная переменная
Write();
Console.WriteLine("\n это Main()");
Console.WriteLine("myString = {0}", myString);
Console.ReadKey();
}
*/
static string myString;//глобальная переменная
static void Write()
{
string myString = "строка из Write()";//локальная переменная
Console.WriteLine("\n это Write()");
Console.WriteLine("Local myString = {0}", myString);
Console.WriteLine("Global myString = {0}", Program.myString);
}
static void Main(string[] args)
{
string myString = "строка из Main()";//локальная переменная
Program.myString = "Global string";
Write();
Console.WriteLine("\n это Main()");
Console.WriteLine("Local myString = {0}", myString);
Console.WriteLine("Global myString = {0}", Program.myString);
Console.ReadKey();
}
}
}
//------------------------------------------------------------------------
Пример 2
//область видимости переменных в других структурах
using System;
namespace Func02
{
class Program
{
/* static void Main(string[] args)
{
int i;
for (i = 0; i < 10; i++)
{
string text = "строка " + Convert.ToString(i);
Console.WriteLine("{0}", text);
}
Console.WriteLine("вывод текста в цикле: {0}", text);//ошибка
}
*/
static void Main(string[] args)
{
int i;
string text;
for (i = 0; i < 10; i++)
{
text = "строка " + Convert.ToString(i);
Console.WriteLine("{0}", text);
}
Console.WriteLine("вывод текста в цикле: {0}", text);//ошибка
/* text - ссылка, которая инициализируется внутри блока, а при
выходе из блока выделенная в нем ОП не доступна (освобождается сборщиком мусора).*/
}
/*
static void Main(string[] args)
{
int i;
string text = " ";
for (i = 0; i < 10; i++)
{
text = "строка " + Convert.ToString(i);
Console.WriteLine("{0}", text);
}
Console.WriteLine("вывод текста в цикле: {0}", text);
Console.ReadKey();
}
*/
}
}
Локальные переменные методов не получают значений по умолчанию автоматически и поэтому должны явно их получать либо через заголовок метода в виде фактических аргументов, либо через оператор присваивания. Компилятор строго следит за этим и при попытке использования переменной без значения выдает ошибку.
Перегрузка функций
Механизм перегрузки функций позволяет создавать множество функций, имеющих одинаковое имя, но работающих с разными типами параметров (имеющих разный код). Прелесть такого использования функций состоит в том, что не требуется указывать явным образом, какая именно из этих версий функции должна использоваться: подходящая версия может быть выбрана компилятором автоматически в зависимости от типа параметров.
Функции
Функции представляют собой блоки кода, позволяющие выполнять одни и те же операции над различными значениями данных. Функции определяются один раз и могут вызываться из любой точки приложения.
Определение функции состоит из следующих элементов:
- Два ключевых слова: static и типа возвращаемого значения (void, если ничего не возвращает).
- Имя функции, за которым следуют круглые скобки, внутри которых размещаются параметры.
- Заключенный в фигурные скобки блок кода, который подлежит выполнению.
Параметры в определении функции обычно называют формальными. Их имена используются в коде функции. При вызове функции на место формальных параметров подставляются их значения (фактические параметры), которые должны указываться точно так, как в определении функции, т.е. в соответствующем количестве и порядке.
Параметры, передаваемые функции, могут быть трех видов: параметры-значения, параметры-ссылки и выходные параметры.
При использовании параметра-значения в функцию передается копия значения переменной из вызывающей функции и ее изменение в функции не изменяет значение переменной в вызывающей функции.
При использовании параметров-ссылок и выходных параметров в функцию передается адрес переменной из вызывающей функции, что дает ей возможность доступа к самой переменной. Параметры-ссылки и выходные параметры используют модификаторы ref и out перед параметром как в определении, так и в вызове функции.
Существуют два важных отличия:
- В качестве параметра ref применять неинициализированную переменную нельзя, а в качестве out – можно.
- Параметр out должен трактоваться функцией, которая его использует, как не имеющий присвоенного значения.
Преимущества использования функций по сравнению с многократным использованием повторяющегося кода:
- Так как код функции хранится в одном месте памяти, это существенно упрощает внесение в него изменений и позволяет при этом избежать множества возможных ошибок.
- Код приложения сокращается за счет группировки внутренних действий и становится удобочитаемым.
Предлагаемое рассмотрение функций охватывает следующие ключевые моменты:
- Определение и использование функций в консольных приложениях.
- Обмен данными с функциями через возвращаемые значения, параметры и глобальные переменные. Передача параметров по ссылке и по значению.
- Использование параметров командной строки функции main().
- Перегрузка функций.
Любой проект консольного или оконного типа должен иметь по крайней мере одну точку входа, определяемую статической функцией Main(). Каждая функция, в том числе и функция Main(), должна принадлежать какому-нибудь классу, т.е. быть методом. Функция Main() объявляется как статический метод, не требующий создания экземпляра (Instance) класса для ее вызова. (Внимание! В приложении, имеющем несколько классов, функция Main() может входить в несколько из них. В этом случае для определения единственной точки входа нужно определить через окно свойств проекта, какой именно класс будет стартовым для данного приложения.)
Обмен данными с функциями через возвращаемые значения, параметры и глобальные переменные.
Глобальные переменные
Скомпилируйте и выполните (по очереди) все фрагменты программ Пример 1 и Пример 2 (включая закомментированные) и объясните результаты.
Пример 1.
//Область видимости переменных в функциях
using System;
namespace Func01
{
class Program
{
/* static void Write()
{
Console.WriteLine("myString = {0}",myString);//ошибка
}
static void Main(string[] args)
{
string myString = "String defined in Main()");//не используется
Write();
Console.ReadKey();
}
*/
//описать последовательность выполнения операторов
/* static void Write()
{
string myString = "строка из Write()";//локальная
Console.WriteLine("\n это Write()!");
Console.WriteLine("myString = {0}", myString);
}
static void Main(string[] args)
{
string myString = "строка из Main()";//локальная переменная
Write();
Console.WriteLine("\n это Main()");
Console.WriteLine("myString = {0}", myString);
Console.ReadKey();
}
*/
static string myString;//глобальная переменная
static void Write()
{
string myString = "строка из Write()";//локальная переменная
Console.WriteLine("\n это Write()");
Console.WriteLine("Local myString = {0}", myString);
Console.WriteLine("Global myString = {0}", Program.myString);
}
static void Main(string[] args)
{
string myString = "строка из Main()";//локальная переменная
Program.myString = "Global string";
Write();
Console.WriteLine("\n это Main()");
Console.WriteLine("Local myString = {0}", myString);
Console.WriteLine("Global myString = {0}", Program.myString);
Console.ReadKey();
}
}
}
//------------------------------------------------------------------------
Пример 2
//область видимости переменных в других структурах
using System;
namespace Func02
{
class Program
{
/* static void Main(string[] args)
{
int i;
for (i = 0; i < 10; i++)
{
string text = "строка " + Convert.ToString(i);
Console.WriteLine("{0}", text);
}
Console.WriteLine("вывод текста в цикле: {0}", text);//ошибка
}
*/
static void Main(string[] args)
{
int i;
string text;
for (i = 0; i < 10; i++)
{
text = "строка " + Convert.ToString(i);
Console.WriteLine("{0}", text);
}
Console.WriteLine("вывод текста в цикле: {0}", text);//ошибка
/* text - ссылка, которая инициализируется внутри блока, а при
выходе из блока выделенная в нем ОП не доступна (освобождается сборщиком мусора).*/
}
/*
static void Main(string[] args)
{
int i;
string text = " ";
for (i = 0; i < 10; i++)
{
text = "строка " + Convert.ToString(i);
Console.WriteLine("{0}", text);
}
Console.WriteLine("вывод текста в цикле: {0}", text);
Console.ReadKey();
}
*/
}
}
Локальные переменные методов не получают значений по умолчанию автоматически и поэтому должны явно их получать либо через заголовок метода в виде фактических аргументов, либо через оператор присваивания. Компилятор строго следит за этим и при попытке использования переменной без значения выдает ошибку.
Использование параметров и возвращаемых значений