Обобщенные структуры
84C# --- Руководство по C# --- Обобщенные структуры
Подобно классам, структуры также могут быть обобщенными. Они очень похожи на обобщенные классы, за исключением возможности наследования. В этой статье рассматривается обобщенная структура 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.ReadLine();
}
}
}
В этом примере экземпляр Nullable<T> создан как Nullable<int>. Переменная х теперь может быть использована как int, т.е. ей можно присваивать значения и применять
в операциях для выполнения некоторых вычислений. Такое поведение стало возможным
благодаря операциям приведения типа Nullable<T>. Однако х также может быть null. Свойства HasValue и Value типа Nullable