Язык программирования C#9 и платформа .NET5
static void SendAPersonByReference(ref Person p){// Изменить некоторые данные в р.p.personAge = 555;// р теперь указывает на новый объект в куче!p = new Person("Nikki", 999);}Как и можно было ожидать, вызываемому коду предоставлена полная свобода в плане манипулирования входным параметром. Вызываемый код может не только изменять состояние объекта, но и переопределять ссылку так, чтобы она указывала на новый объект
. Взгляните на следующий обновленный код:Person// Передача ссылочных типов по ссылке.Console.WriteLine("***** Passing Person object by reference *****");...Person mel = new Person("Mel", 23);Console.WriteLine("Before by ref call, Person is:");// Перед вызовом с передачей по ссылкеmel.Display();SendAPersonByReference(ref mel);Console.WriteLine("After by ref call, Person is:");// После вызова с передачей по ссылкеmel.Display();Console.ReadLine();Вот вывод:
***** Passing Person object by reference *****Before by ref call, Person is:Name: Mel, Age: 23After by ref call, Person is:Name: Nikki, Age: 999Здесь видно, что после вызова объект по имени
возвращается как объект по имениMel, поскольку метод имел возможность изменить то, на что указывала в памяти входная ссылка. Ниже представлены основные правила, которые необходимо соблюдать при передаче ссылочных типов.Nikki• Если ссылочный тип передается по ссылке, тогда вызываемый код может изменять значения данных состояния объекта, а также объект, на который указывает ссылка.
• Если ссылочный тип передается по значению, то вызываемый код может изменять значения данных состояния объекта, но не объект, на который указывает ссылка.
Заключительные детали относительно типов значений и ссылочных типов
В завершение данной темы в табл. 4.4 приведена сводка по основным отличиям между типами значений и ссылочными типами.
Несмотря на различия, типы значений и ссылочные типы могут реализовывать интерфейсы и поддерживать любое количество полей, методов, перегруженных операций, констант, свойств и событий.
Понятие типов С#, допускающих null
Давайте исследуем роль типов данных, допускающих значение
, с применением проекта консольного приложения по имениnull. Как вам уже известно, типы данных C# обладают фиксированным диапазоном значений и представлены в виде типов пространства имен System. Например, тип данныхFunWithNullableValueTypesможет принимать только значения из набора (System.Boolean,true. Вспомните, что все числовые типы данных (а такжеfalse)) являются типами значений. Типам значений никогда не может быть присвоено значениеBoolean, потому что оно служит для представления пустой объектной ссылки.null// Ошибка на этапе компиляции!// Типы значений нельзя устанавливать в null!bool myBool = null;int myInt = null;В языке C# поддерживается концепция типов данных, допускающих значение
. Выражаясь просто, допускающийnullтип может представлять все значения лежащего в основе типа плюсnull. Таким образом, если вы объявите переменную типаnull, допускающегоbool, то ей можно будет присваивать значение из набораnull. Это может быть чрезвычайно удобно при работе с реляционными базами данных, поскольку в таблицах баз данных довольно часто встречаются столбцы, для которых значения не определены. Без концепции типов данных, допускающих{true, false, null}, в C# не было бы удобного способа для представления числовых элементов данных без значений.nullЧтобы определить переменную типа, допускающего
, необходимо добавить к имени интересующего типа данных суффикс в виде знака вопроса (null). До выхода версии C# 8.0 такой синтаксис был законным только в случае применения к типам значений (более подробные сведения ищите в разделе "Использование ссылочных типов, допускающих?" далее в главе). Подобно переменным с типами, не допускающимиnull, локальным переменным, имеющим типы, которые допускаютnull, должно присваиваться начальное значение, прежде чем ими можно будет пользоваться:nullstatic void LocalNullableVariables(){// Определить несколько локальных переменных// с типами, допускающими nullint? nullableInt = 10;double? nullableDouble = 3.14;bool? nullableBool = null;char? nullableChar = 'a';int?[] arrayOfNullableInts = new int?[10];}Использование типов значений, допускающих null
В языке C# система обозначений в форме суффикса
представляет собой сокращение для создания экземпляра обобщенного типа структуры?. Она также применяется для создания ссылочных типов, допускающихSystem.Nullable<T>, но ее поведение несколько отличается. Хотя подробное исследование обобщений мы отложим до главы 10, сейчас важно понимать, что типnullпредоставляет набор членов, которые могут применяться всеми типами, допускающимиSystem.Nullable<T>.null
