- •Пишем первую программу на Си-шарп
- •Переменные,типы данных, константы в Си-шарп
- •Var сохраняет принцип строгой типизации в Си-шарп. Это означает, что после того, как для переменной уже был определен тип, в нее нельзя записать данные другого типа:
- •Арифметические и логические операции в Си-шарп
- •Условные операторы в Си-шарп. Тернарный оператор
- •Массивы в Си-шарп. Класс List
- •Удаление элементов
- •Оператор цикла foreach в Си-шарп
- •Функции в Си-шарп. Оператор return
- •Работа со строками в Си-шарп. Класс String
- •Обработка исключений в Си-шарп. Оператор try-catch
- •Работа с файлами в Си-шарп. Классы StreamReader и StreamWriter
- •Понятие объектно-ориентированного программирования (ооп). Классы и объекты
- •Классы в Си-шарп. Объявление классов и создание объектов
- •Методы в Си-шарп. Разница между простыми и статическими
- •Конструкторы в Си-шарп. Указатель this
- •Наследование в Си-шарп. Конструктор базового класса
- •Массив указателей на базовый класс в Си-шарп. Операторы is и as
- •Полиморфизм в Си-шарп. Что это такое?
- •Виртуальные методы в Си-шарп. Переопределение методов
- •Абстрактные классы, методы и свойства в Си-шарп
- •Инкапсуляция в Си-шарп. Модификаторы доступа
- •Ерегрузка операторов в Си-шарп
- •Символы повторения
- •Символы привязки
- •Символы выбора
- •Другие символы
- •Ссылочные типы и типы значений в Си-шарп. Ключевые слова ref и out
- •Значение Null. Nullable-типы. Оператор ??
- •Структуры в Си-шарп
- •Сетевое программирование в Си-шарп
- •Протокол http, метод post и куки в Си-шарп
Ссылочные типы и типы значений в Си-шарп. Ключевые слова ref и out
В языке Си-шарп все типы данных делятся на две категории – ссылочные типы, и типы значений. Они отличаются способом хранения в памяти, производительностью и другим. В этом уроке мы поговорим, что это всё означает, а также о передаче параметров в метод по ссылке (ключевые слова ref и out). Типы значений Эту категорию также называют структурными типами. Типы значений хранятся в стеке. Стек - это область памяти, которая используется для передачи параметров в методы и хранения определенных в пределах методов локальных переменных. Данные переменной типа значения хранятся в самой переменной. К типам значений относятся: - Целочисленные типы (byte, sbyte, char, short, ushort, int, uint, long, ulong); - Типы с плавающей запятой (float, double); - Тип decimal; - Тип bool; - Пользовательские структуры (struct); - Перечисления (enum). Код ниже показывает, что при присвоении значения одной переменной значимого типа другой, дальнейшее изменение одной из переменных не влияет на другую. Так потому, что хранение данных значимого типа происходит в самой переменной:
static void Main(string[] args) { int a = 1; int b = 2; b = a; a = 3; Console.WriteLine(a); // 3 Console.WriteLine(b); // 1 }
Ссылочные типы Переменная ссылочного типа содержит не данные, а ссылку на них. Сами данные в этом случае уже хранятся в куче. Куча - это область памяти, в которой размещаются управляемые объекты, и работает сборщик мусора. Сборщик мусора освобождает все ресурсы и объекты, которые уже не нужны. К ссылочным типам относятся: - Классы (class); - Интерфейсы (interface); - Делегаты (delegate); - Тип object; - Тип string. В коде ниже был создан простой класс, в котором есть одно поле типа int. Дальше была проделана такая же процедура, как и в случае выше, только результат уже другой. После присвоения одного объекта другому, они стали указывать на одну и ту же область памяти (меняем b – меняется и a):
class Test { public int x; } class Program { static void Main(string[] args) { Test a = new Test(); Test b = new Test(); a.x = 1; b.x = 2; b = a; // присвоение ссылки b.x = 3; Console.WriteLine(a.x); // 3 Console.WriteLine(b.x); // 3 } }
Передача параметров в метод по ссылке. Операторы ref и out В C# значения переменных по-умолчанию передаются по значению (в метод передается локальная копия параметра, который используется при вызове). Это означает, что мы не можем внутри метода изменить параметр из вне:
public static void ChangeValue(object a) { a = 2; } static void Main(string[] args) { int a = 1; ChangeValue(a); Console.WriteLine(a); // 1 Console.ReadLine(); }
Чтобы передавать параметры по ссылке, и иметь возможность влиять на внешнюю переменную, используются ключевые слова ref и out. Ключевое слово ref Чтобы использовать ref, это ключевое слово стоит указать перед типом параметра в методе, и перед параметром при вызове метода:
public static void ChangeValue(ref int a) { a = 2; } static void Main(string[] args) { int a = 1; ChangeValue(ref a); Console.WriteLine(a); // 2 Console.ReadLine(); }
В этом примере мы изменили значение внешней переменной внутри метода. Особенностью ref является то, что переменная, которую мы передаем в метод, обязательно должна быть проинициализирована значением, иначе компилятор выдаст ошибку «Use of unassigned local variable 'a'». Это является главным отличием ref от out. Ключевое слово out Out используется точно таким же образом как и ref, за исключением того, что параметр не обязан быть проинициализирован перед передачей, но при этом в методе переданному параметру обязательно должно быть присвоено новое значение:
public static void ChangeValue(out int a) { a = 2; } static void Main(string[] args) { int a; ChangeValue(out a); Console.WriteLine(a); // 2 Console.ReadLine(); }
Если не присвоить новое значение параметру out, мы получим ошибку «The out parameter 'a' must be assigned to before control leaves the current method» Производительность Учитывая тот факт, что по умолчанию в метод передаются параметры по значению и создаются их копии в стеке, при использовании сложных типов данных (пользовательские структуры), или если метод вызывается много раз, это плохо скажется на производительности. В таком случае также стоит использовать ключевые слова ref и out. Если говорить в целом о ссылочных типах и типах значений, то производительность приложения упадет, если использовать только ссылочные типы. На создание переменной ссылочного типа в куче выделяется память под данные, а в стеке под ссылку на эти данные. Для типов значений память выделяется только в стеке. Время на размещение данных в стеке меньше, чем в куче, это также идет в плюс типам значений в плане производительности.
