Как упоминалось выше, при написании обобщенного кода иногда важно провести различие между типами значений и ссылочными типами. Такая потребность возникает, в частности, в том случае, если переменной параметра типа должно быть присвоено значение по умолчанию. Для ссылочных типов значением по умолчанию является null
, для неструктурных типов значений — 0 или логическое значение false
, если это тип bool
, а для структур типа struct
— объект соответствующей структуры с полями, установленными по умолчанию. В этой связи возникает вопрос: какое значение следует присваивать по умолчанию переменной параметра типа: null
, 0 или нечто другое? Например, если в следующем объявлении класса Test
:
class Test
Т obj;
// ...
переменной obj требуется присвоить значение по умолчанию, то какой из двух вариантов
obj = null; // подходит только для ссылочных типов или
obj =0; // подходит только для числовых типов и
// перечислений, но не для структур
следует выбрать? Для разрешения этой дилеммы можно воспользоваться еще одной формой оператора default
, приведенной ниже.
default(тип)
Эта форма оператора default
пригодна для всех аргументов типа, будь то типы значений или ссылочные типы.
Ниже приведен короткий пример, демонстрирующий данную форму оператора
default
.
// Продемонстрировать форму оператора default.
using System;
class MyClass {
//...
}
// Получить значение, присваиваемое параметру типа Т по умолчанию,
class Test
public T obj;
public Test() {
// Следующий оператор годится только для ссылочных типов.
// obj = null; //не годится
// Следующий оператор годится только для типов значений.
// obj = 0; // не годится
// А этот оператор годится как для ссылочных типов,
// так и для типов значений,
obj = default(T); // Годится!
}
// ...
}
class DefaultDemo {
static void Main() {
// Сконструировать объект класса Test, используя ссылочный тип.
Test
if (x.obj == null)
Console.WriteLine("Переменная x.obj имеет пустое значение
// Сконструировать объект класса Test, используя тип значения.
Test
if (у.obj == 0)
Console.WriteLine("Переменная у.obj имеет значение 0.");
}
}
Вот к какому результату приводит выполнение этого кода.
Переменная x.obj имеет пустое значение
Переменная у.obj имеет значение 0.
Обобщенные структуры
В C# разрешается создавать обобщенные структуры. Синтаксис для них такой же, как и для обобщенных классов. В качестве примера ниже приведена программа, в которой создается обобщенная структура XY для хранения координат X, Y.
// Продемонстрировать применение обобщенной структуры,
using System;
// Эта структура является обобщенной,
struct XY
T х;
T y;
public XY(T а, T b) {
х = а;
y = b;
}
public T X {
get { return х; }
set { х = value; }
}
public T Y {
get { return y; }
set { y = value; }
}
}
class StructTest {
static void Main() {
XY
XY
Console.WriteLine(xy.X + ", " + xy.Y);
Console.WriteLine(xy2.X + ", " + xy2.Y);
}
}
При выполнении этой программы получается следующий результат.
10, 20
88, 99
Как и на обобщенные классы, на обобщенные структуры могут накладываться ограничения. Например, на аргументы типа в приведенном ниже варианте структуры XY накладывается ограничение типа значения.
struct XY
// ...
Создание обобщенного метода