Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

• Если ссылочный тип передается по ссылке, тогда вызываемый код может изменять значения данных состояния объекта, а также объект, на который указывает ссылка.

• Если ссылочный тип передается по значению, то вызываемый код может изменять значения данных состояния объекта, но не объект, на который указывает ссылка.

Заключительные детали относительно типов значений и ссылочных типов

В завершение данной темы в табл. 4.4 приведена сводка по основным отличиям между типами значений и ссылочными типами.

Несмотря на различия, типы

значений и ссылочные типы могут реализовывать интерфейсы и поддерживать любое количество полей, методов, перегруженных операций, констант, свойств и событий.

Понятие типов С#, допускающих null

Давайте исследуем роль типов данных, допускающих значение

null
, с применением проекта консольного приложения по имени
FunWithNullableValueTypes
. Как вам уже известно, типы данных C# обладают фиксированным диапазоном значений и представлены в виде типов пространства имен System. Например, тип данных
System.Boolean
может принимать только значения из набора (
true
,
false)
. Вспомните, что все числовые типы данных (а также
Boolean
) являются типами значений. Типам значений никогда не может быть присвоено значение
null
, потому что оно служит для представления пустой объектной ссылки.

// Ошибка на этапе компиляции!

// Типы значений нельзя устанавливать в null!

bool myBool = null;

int myInt = null;

В языке C# поддерживается концепция типов данных, допускающих значение

null
. Выражаясь просто, допускающий
null
тип может представлять все значения лежащего в основе типа плюс
null
. Таким образом, если вы объявите переменную типа
bool
, допускающего
null
, то ей можно будет присваивать значение из набора
{true, false, null}
. Это может быть чрезвычайно удобно при работе с реляционными базами данных, поскольку в таблицах баз данных довольно часто встречаются столбцы, для которых значения не определены. Без концепции типов данных, допускающих
null
, в C# не было бы удобного способа для представления числовых элементов данных без значений.

Чтобы определить переменную типа, допускающего

null
, необходимо добавить к имени интересующего типа данных суффикс в виде знака вопроса (
?
). До выхода версии C# 8.0 такой синтаксис был законным только в случае применения к типам значений (более подробные сведения ищите в разделе "Использование ссылочных типов, допускающих
null
" далее в главе). Подобно переменным с типами, не допускающими
null
, локальным переменным, имеющим типы, которые допускают
null
, должно присваиваться начальное значение, прежде чем ими можно будет пользоваться:

static void LocalNullableVariables

{

// Определить несколько локальных переменных

// с типами, допускающими null

int? nullableInt = 10;

double? nullableDouble = 3.14;

bool? nullableBool = null;

char? nullableChar = 'a';

int?[] arrayOfNullableInts = new int?[10];

}

Использование типов значений, допускающих null

В языке C# система обозначений в форме суффикса

?
представляет собой сокращение
для создания экземпляра обобщенного типа структуры
System.Nullable<T>
. Она также применяется для создания ссылочных типов, допускающих
null
, но ее поведение несколько отличается. Хотя подробное исследование обобщений мы отложим до главы 10, сейчас важно понимать, что тип
System.Nullable<T>
предоставляет набор членов, которые могут применяться всеми типами, допускающими
null
.

Например, с помощью свойства

HasValue
или операции
!=
можно программно выяснять, действительно ли переменной, допускающей
null
, было присвоено значение
null
. Значение, которое присвоено типу, допускающему
null
, можно получать напрямую или через свойство
Value
. Учитывая, что суффикс
?
является просто сокращением для использования
Nullable<T>
, предыдущий метод
LocalNullableVariables
можно было бы реализовать следующим образом:

static void LocalNullableVariablesUsingNullable

{

// Определить несколько типов, допускающих null,

// с применением Nullable<T>.

Nullable<int> nullableInt = 10;

Nullable<double> nullableDouble = 3.14;

Nullable<bool> nullableBool = null;

Nullable<char> nullableChar = 'a';

Nullable<int>[] arrayOfNullableInts = new Nullable<int>[10];

}

Как отмечалось ранее, типы данных, допускающие

null
, особенно полезны при взаимодействии с базами данных, потому что столбцы в таблицах данных могут быть намеренно оставлены пустыми (скажем, быть неопределенными). В целях демонстрации рассмотрим показанный далее класс, эмулирующий процесс доступа к базе данных с таблицей, в которой два столбца могут принимать значения
null
. Обратите внимание, что метод
GetlntFromDatabase
не присваивает значение члену целочисленного типа, допускающего
null
, тогда как метод
GetBoolFromDatabase
присваивает допустимое значение члену типа
bool
?

class DatabaseReader

{

// Поле данных типа, допускающего null.

public int? numericValue = null;

public bool? boolValue = true;

// Обратите внимание на возвращаемый тип, допускающий null.

public int? GetIntFromDatabase

{ return numericValue; }

// Обратите внимание на возвращаемый тип, допускающий null.

public bool? GetBoolFromDatabase

{ return boolValue; }

}

В следующем коде происходит обращение к каждому члену класса

DatabaseReader
и выяснение присвоенных значений с применением членов
HasValue
и
Value
, а также операции равенства C# (точнее операции "не равно"):

Console.WriteLine("***** Fun with Nullable Value Types *****\n");

DatabaseReader dr = new DatabaseReader;

Поделиться с друзьями: