Начиная с первых версий языка C# мы могли использовать в методе параметры с ключевым словом ref. В версии C# 7.0 (Visual Studio 2017) была добавлена возможность возвращать ссылку на объект с помощью ключевого слова ref и определять локальную переменную, которая будет хранить ссылку.
Локальная переменная-ссылка
Для определения локальной переменной-ссылки (ref local) перед ее типом ставится ключевое слово ref:
1 2 | int x = 5; ref int xRef = ref x; |
Здесь переменная xRef указывает не просто на значение переменной x, а на область в памяти, где располагается эта переменная. Для этого перед x также указывается ref.
При этом мы не можем просто определить переменную-ссылку, нам обязательно надо присвоить ей некоторое значение. Так, следующий код вызовет ошибку:
1 | ref int xRef; // ошибка |
Получив ссылку, мы можем манипулировать значением по этой ссылке. Например:
1 2 3 4 5 6 7 8 9 10 | static void Main(string[] args) { int x = 5; ref int xRef = ref x; Console.WriteLine(x); // 5 xRef = 125; Console.WriteLine(x); // 125 Console.Read(); } |
Ссылка как результат функции
Для возвращения из функции ссылки в сигнатуре функции перед возвращаемым типом, а также после оператора return следует указать ключевое слово ref:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | static void Main(string[] args) { int[] numbers = { 1, 2, 3, 4, 5, 6, 7 }; ref int numberRef = ref Find(4, numbers); // ищем число 4 в массиве numberRef = 9; // заменяем 4 на 9 Console.WriteLine(numbers[3]); // 9 Console.Read(); } static ref int Find(int number, int[] numbers) { for (int i = 0; i < numbers.Length; i++) { if (numbers[i] == number) { return ref numbers[i]; // возвращаем ссылку на адрес, а не само значение } } throw new IndexOutOfRangeException("число не найдено"); } |
В методе Find ищем число в массиве, но вместо самого значения числа возвращаем ссылку на него в памяти. Для этого в сигнатуре метода в качестве типа результата функции указывается не просто int, а ref int.
Кроме того, в самом методе после слова return также ставится ref:
1 | return ref numbers[i]; |
Тем самым мы получаем не просто значение, а ссылку на объект в памяти.
В методе Main для определения переменной, которая буде содержать ссылку, используется ключевое слово ref. При вызове метода также указывается слово ref:
1 | ref int numberRef = ref Find(7, numbers); |
В итоге переменная numberRef будет содержать ссылку на объект int, и через данную переменную в последствии мы можем изменить объект по этой ссылке.
Лекция 21. Работа с консолью
Для взаимодействия с консолью нам необходим класс Console. Ранее мы уже использовали вывод на консоль с помощью методаWriteLine, теперь же разберем этот класс подробнее.
Класс Console представляет ряд методов для взаимодействия с консолью:
· Beep: подача звукового сигнала
· Clear: очистка консоли
· WriteLine: вывод строки текста, включая символ возврата каретки (то есть с переводом на новую строку)
· Write: вывод строки текста, но без символа возврата каретки
· ReadLine: считывание строки текста со входного потока
· Read: считывание введенного символа в виде числового кода данного символа. С помощью преобразования к типу char мы можем получить введенный символ
· ReadKey: считывание нажатой клавиши клавиатуры (ConsoleKeyInfo key= Console.ReadKey();)
Кроме того, класс Console обладает свойствами, которые позволяют управлять консолью. Некоторые из них:
· BackgroundColor: цвет фона консоли
· ForegroundColor: цвет шрифта консоли
· BufferHeight: высота буфера консоли
· BufferWidth: ширина буфера консоли
· Title: заголовок консоли
· WindowHeight и WindowWidth: высота и ширина консоли соответственно
Напишем небольшое приложение. Оно будет принимать два числа, введенные пользователем, и отображать их сумму. Приложение будет иметь следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Program { static void Main(string[] args) { // установка зеленого цвета шрифта Console.ForegroundColor=ConsoleColor.DarkGreen; try { do { Console.WriteLine("Введите первое число"); int num1 = Int32.Parse(Console.ReadLine()); Console.WriteLine("Введите второе число"); int num2 = Int32.Parse(Console.ReadLine()); Console.WriteLine("Сумма чисел {0} и {1} равна {2}", num1, num2, num1 + num2); Console.WriteLine("Для выхода нажмите Escape; для продолжения - любую другую клавишу"); } while (Console.ReadKey().Key!= ConsoleKey.Escape); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadLine(); } } } |
Вначале устанавливаем цвет шрифта консоли. Все доступные цвета хранятся в перечислении ConsoleColor.
Далее помещаем весь используемый код в блок try, поскольку у нас может возникнуть исключение в ходе преобразования строки в число (если мы введем нечисловые символы).
Непосредственно код программы представляет цикл do...while, из которого можно выйти, только нажав на клавишу Escape.
С помощью метода Int32.Parse преобразуем введенную сроку в число: int num1 = Int32.Parse(Console.ReadLine());
Тема 3. Объектно-ориентированное программирование. Классы