Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


Открытые и закрытые типы




Типы с обобщенными параметрами-типами также считаются типами, причем для каждого из них CLR создает внутренний объект-тип. Это справедливо для ссылочных типов (классов), значимых типов (структур), интерфейсов и делегатов. Но тип с обобщенными параметрами-типами называют открытым типом, а в CLR запрещено конструирование экземпляров открытых типов (как и экземпляров типов-интерфейсов).

При ссылке на обобщенный тип в коде можно определить набор обобщенных аргументов-типов. Если всем аргументам-типам определенного типа передать действительные типы данных, то такой тип будут называть закрытым. CLR разрешает создание экземпляров закрытых типов. Но в коде, ссылающемся на обобщенный тип, можно не определять все обобщенные аргументы-типы. Таким образом, в CLR создается новый объект открытого типа, экземпляры которого создавать нельзя. Следующий код проясняет ситуацию.

 

using System;

using System.Collections.Generic;

 

// Частично определенный открытый тип.

internal sealed class DictionaryStringKey<TValue> : Dictionary<String, TValue>

{}

public static class Program

{

public static void Main()

{

Object o = null;

 

// Dictionary<,> - это открытый тип с двумя параметрами-типами.

Type t = typeof(Dictionary<,>);

 

// Попытка создания экземпляра этого типа (неудачная),

o = CreateInstance(t);

Console.WriteLine();

 

// DictionaryStringKey<> - это открытый тип с одним параметром-типом,

t = typeof(DictionaryStringKey<>);

 

// Попытка создания экземпляра этого типа (неудачная),

o = CreateInstance(t);

Console.WriteLine();

 

// DictionaryStringKey<Guid> - это закрытый тип.

t = typeof(DictionaryStringKey<Guid>);

 

// Попытка создания экземпляра этого типа (удачная),

o = CreateInstance(t);

 

// Проверка успешности попытки.

Console.WriteLine("Object type=" + o.GetType());

Console.ReadKey();

}

private static Object CreateInstance(Type t)

{

Object o = null;

try

{

o = Activator.CreateInstance(t);

Console.Write("Created instance of {0}", t.ToString());

}

catch (ArgumentException e)

{

Console.WriteLine(e.Message);

}

return o;

}

}

 

Скомпилировав и выполнив этот код, вы увидите:

Cannot create an instance of System.Collections.Generic.

Dictionary'2[TKey,TValue] because Type.ContainsGenericParameters is true.

Cannot create an instance of DictionaryStringKey'1[TValue] because Type.ContainsGenericParameters is true.

Created instance of DictionaryStringKey'1[System.Guid] Object type=DictionaryStringKey'1[System.Guid]

Итак, при попытке создания экземпляра открытого типа метод Createlnstance объекта Activator генерирует исключение ArgumentException. На самом деле, сообщение об исключении означает, что тип все же содержит несколько обобщенных параметров.

В выводимой программой информации видно, что имена типов заканчиваются левой одиночной кавычкой ('), за которой следует число, означающее арность типа, то есть число необходимых для него параметров-типов. Например, арность класса Dictionary равна 2, потому что требуется определить типы ТКеу и TValue. Арность класса DictionaryStringKey — 1, так как требуется указать лишь один тип — TValue.

Также замечу, что CLR размещает статические поля типа в самом объекте-типе - поэтому у каждого закрытого типа есть свои статические поля. Иначе говоря, статические поля, определенные в объекте List<T>, не будут совместно использоваться объектами List<DateTime> и List<String>, потому что у каждого объекта закрытого типа есть свои статические поля. Если же в обобщенном типе определен статический конструктор, то последний выполняется для закрытого типа лишь раз. Иногда разработчики определяют статический конструктор для обобщенного типа, чтобы аргументы-типы соответствовали определенным критериям. Например, так определяется обобщенный тип, используемый только с перечислимыми типами.

 

internal sealed class GenericTypeThatRequiresAnEnum<T>

{

static GenericTypeThatRequiresAnEnum()

{

if (!typeof(T).IsEnum)

{

throw new ArgumentException("T must be an enumerated type");

}

}

}

 

В CLR есть функция под названием ограничения — это более удачный способ определения обобщенного типа с указанием допустимых для него аргументов-типов. Но подробнее о них чуть позже. К сожалению, эта функция не позволяет ограничить аргументы-типы только перечислимыми типами. Поэтому в предыдущем примере необходим статический конструктор для проверки того, что используемый тип является перечислимым.

 


Поделиться:

Дата добавления: 2015-04-21; просмотров: 101; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.01 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты