Область видимости и время существования переменных
До сих пор мы объявляли переменные либо в методе Main(), либо в методах класса. В C# разрешается объявлять переменные внутри любого блока. Любой блок определяет область объявления, или область видимости объектов. Область видимости также определяет и время существования (жизни) этих объектов. Самыми важными являются области видимости, которые определены классом и методом. Область видимости, определяемая методом, начинается с начала тела метода {…}. Если метод имеет параметры, то они также относятся к области видимости метода.
При объявлении переменной внутри области видимости мы ее локализируем, защищаем от неправомочного доступа и/или модификации. Эти правила области видимости обеспечивают основу для инкапсуляции.
Области видимости могут быть вложенными:
int x=53;
if (x >= 10)
{
double y =x* 20.54;
x *= 2;
Console. WriteLine(“x= ”+x”, y= ”+y);
}
Здесь переменная y объявлена в блоке оператора if. Внешняя область видимости (int x=53;) включает внутреннюю, т.е. x виден в if. Объекты, объявленные во внутренней области, не видимы вне ее. Если за if написать y=100; то будет ошибка.
Переменные создаются после входа в область видимости, а разрушаются при выходе из нее. Это означает, что переменная не будет хранить значение за пределами области видимости. Таким образом, переменная, объявленная внутри некоторого метода, не будет хранить значение между вызовами этого метода. И, аналогично, переменная, объявленная внутри какого-либо блока, потеряет свое значение по завершению этого блока.
Итак:
1) время существования переменной («цикл жизни») ограничивается ее областью видимости;
2) ни одна переменная, объявленная во внутренней области видимости, не может иметь имя, совпадающее с именем переменной, объявленной во внешней области видимости.
7.2. Преобразование и приведение типов данных
Часто возникает необходимость переменной одного типа присвоить значение переменной другого типа. При этом нужно преобразовать данные из одного типа в другой. Преобразование между типами данных может быть двух видов: неявное (автоматическое) и явное.
Неявное преобразование – это преобразование типов данных, которое явно не задано и выполняется без специально указанной команды, т.е. такие преобразования выполняются автоматически. Они никогда не приводят к потере или повреждению информации. Автоматическое преобразование будет выполнено, если:
– оба типа совместимы;
– тип переменной-приемника «больше» (т.е. имеет больший диапазон представления значений), чем тип источника.
При соблюдении этих двух условий выполняется преобразование с расширением или расширяющее преобразование. Например, тип int – достаточно «большой» тип, чтобы сохранить значение типа byte или short. byte и int – это целочисленные типы, поэтому они совместимы. Преобразование типов из long в double является расширяющим, а обратное преобразование из double в long автоматически не выполняется, т.к. это преобразование не является расширяющим.
Разрешены следующие преобразования числовых типов:
1) sbyte (-128 до 127) к типам short, int, long, float, double, decimal;
2) byte (0-255) к типам short, ushort, int, uint, long, ulong, float, double, decimal;
3) short к типам int, long, float, double, decimal;
4) ushort к типам int, uint, long, ulong, float, double, decimal;
5) int к типам long, float, double, decimal;
6) uint к типам long, ulong, float, double, decimal;
7) long к типам float, double, decimal;
8) ulong к типам float, double, decimal;
9) char к типам ushort, int, uint, long, ulong, float, double, decimal;
10) float к типу double.
Явное преобразование или приведение к типу – это явно заданная инструкция компилятору преобразовать один тип в другой. Инструкция записывается так: (тип_приемника) выражение.
Например: double x, y;
x = 50, y = 30;
int z = (int) (x/y);
Если приведение приводит к сужающему преобразованию, то возможна потеря информации. Преобразование типов может встречаться и в выражениях, а не только при присваивании переменных. Преобразование типов выполняется на основе правил продвижения по «типовой» лестнице. Например, если один операнд имеет тип double, то и второй преобразуется в double, или, один операнд имеет тип uint, то и второй преобразуется в uint, иначе оба операнда преобразуются в значение типа int.
Однако продвижение типов может иметь неожиданные последствия. Рассмотрим пример, где арифметическая операция включает два byte-значения. Тогда сначала byte-операнды «подтягиваются» до типа int, а затем вычисляется результат, который имеет тип int:
byte b;
b=5; b=(byte) (b*b); // (b*b) – подтягивается к int, необходимо
// приведение типов, а иначе будет int.
Задание: Вычислить значение корня квадратного из числа x, а так же его целую часть.
double x;
Console.WriteLine("Введите действительное число x");
x = Double.Parse(Console.ReadLine());
Console.WriteLine("Корень из числа {0:0.##} = {1:0.##}, его целая часть = {2:0.##}", x, Math.Sqrt(x), (int)Math.Sqrt(x));
// Выполнить!
Использование приведения типов для параметров-объектов методов классов. Модификатор рarams и ключевое слово is.В метод можно передавать с помощью модификатора params массив объектов, т.е. массив, состоящий из чего угодно.
Задание: В проекте «Первые_учебные_классы» имеется 3 класса: Natur_Chisla, Point , Num_Array . Создать общий метод Show_Object(…) в любом классе (например, в Natur_Chisla), который принимает массив объектов. Метод проверит типы объектов-параметров. Если среди поступивших в метод обнаружатся объекты одно из данных классов, то будет вызван метод Show() соответствующего класса, иначе на экран выводится соответствующее сообщение.
//В классе Natur_Chisla:
public void Show_Object(params object[] mas)
{
if (mas.Length == 0)
{
Console.WriteLine("Массив объектов пуст!");
return;
}
for (int i = 0; i < mas.Length; i++)
if (mas[i] is Natur_Chisla)
((Natur_Chisla) mas[i]).Show();
Else
if (mas[i] is Point)
((Point)mas[i]).Show();
else
if (mas[i] is Num_Array)
((Num_Array) mas[i]).Show();
else
Console.WriteLine(mas[i] + " не является объектом классов данного проекта.");
}
//В Main():
Требуется восстановить следующие строки программного кода:
Natur_Chisla Ob1 = new Natur_Chisla();
Natur_Chisla Ob2 = new Natur_Chisla(37, 18);
Point T1 = new Point();
Point T2 = new Point(18.51, -39);
Num_Array.Input_size();
Num_Array Ob_mas = new Num_Array();
Ob_mas.Input_mas();
Теперь приступаем к тестированию метода:
Ob1.Show_Object(Ob2);
//Выполнить!
Ob1.Show_Object(Ob_mas, Ob2);
//выполнить!
Ob1.Show_Object(T2, Ob_mas, Ob2);
//Выполнить!
Ob1.Show_Object(13.87, T1, Ob_mas, Ob2);
//Выполнить!
Ob1.Show_Object();
//Выполнить!