Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Руководство_по_C#.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
10.01 Mб
Скачать

11.10Обобщенные структуры

Подобно классам, структуры также могут быть обобщенными. Они очень похожи на обобщенные классы, за исключением возможности наследования. В этой статье рассматривается обобщенная структура Nullable<T>, которая определена в .NET Framework. Итак, примером обобщенной структуры в .NET Framework является Nullable<T>.

Число в базе данных и число в языке программирования имеют важное отличие в своих характеристиках, поскольку число в базе данных может быть null. Число в C# не может быть null. Проблема существует не только с базами данных, но также с отображением данных XML на типы .NET.

Это отличие часто служит источником сложностей и требует массы дополнительной работы по отображению данных. Одно из решений состоит в отображении чисел из баз данных и файлов XML на ссылочные типы, потому что ссылочные типы могут иметь значение null. Однако это также означает дополнительные накладные расходы во время выполнения.

За счет использования структуры Nullable<T> эта проблема может быть легко решена. Ниже показан фрагмент кода с упрощенной версией определения типа Nullable<T>. Структура Nullable<T> определяет ограничение, которое состоит в том, что обобщенный тип T должен быть структурой. С классами в качестве обобщенных типов преимущество минимальных накладных расходов исчезло бы, и поскольку объекты классов все равно могут быть null, то в использовании класса с типом Nullable<T> смысла нет.

Единственное дополнение к типу Т, определенное в Nullable<T>, это поле типа bool hasValue, которое определяет, установлено значение или же оно равно null. Помимо этого, обобщенная структура определяет доступные только для чтения свойства HasValue и Value, а также перегрузки некоторых операций. Перегрузка операции приведения Nullable<T> к T определена явно, так как она может генерировать исключение в случае, если hasValue равно false. Перегрузка операции для приведения к Nullable<T> определена неявно, потому что она всегда успешна:

using System;

namespace ConsoleApplication1

{

public struct Nullable<T> where T : struct

{

public Nullable(T value)

{

this.hasValue = true;

this.value = value;

}

private bool hasValue;

public bool HasValue { get {return hasValue; } }

private T value;

public T Value

{

get

{ if (!hasValue)

throw new InvalidOperationException("no value");

return value;

}

}

public static explicit operator T(Nullable<T> value)

{ return value.Value; }

public static implicit operator Nullable<T>(T value)

{ return new Nullable<T>(value); }

public override string ToString()

{

if (!HasValue) return String.Empty;

return this.value.ToString();

}

}

class Program

{

static void Main()

{

Nullable<int> x;

x = 4;

Console.ReadKey();

}

}

}

В этом примере экземпляр Nullable<T> создан как Nullable<int>. Переменная х теперь может быть использована как int, т.е. ей можно присваивать значения и применять в операциях для выполнения некоторых вычислений. Такое поведение стало возможным благодаря операциям приведения типа Nullable<T>. Однако х также может быть null. Свойства HasValue и Value типа Nullable могут проверять, есть ли значение, и обращаться к нему.