Опубликован: 22.11.2005 | Уровень: специалист | Доступ: платный | ВУЗ: Тверской государственный университет
Лекция 6:

Выражения. Операции в выражениях

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >

Операции sizeof и typeof

Операция sizeof возвращает размер значимых типов, заданный в байтах. Пояснения требуют некоторые особенности ее применения. Она должна выполняться только в небезопасных блоках. Поэтому проект, в котором она может использоваться, должен быть скомпилирован с включенным свойством /unsafe. На рис. 6.1 показано, как на странице свойств проекта можно включить это свойство:

Включение свойства /unsafe

Рис. 6.1. Включение свойства /unsafe

Далее необходимо создать небезопасный блок, например, метод класса, помеченный как unsafe, в котором уже можно вызывать эту функцию (операцию). Приведу пример такого метода, созданного в классе Testing:

/// <summary>
/// определение размеров и типов
/// </summary>
unsafe public static void SizeMethod()
{
	Console.WriteLine("Размер типа Boolean = " + sizeof(bool));
	Console.WriteLine("Размер типа double = " + sizeof(double));
	Console.WriteLine("Размер типа char = " + sizeof(System.Char));
	int b1=1;
	Type t = b1.GetType();
	Console.WriteLine("Тип переменной b1: {0}", t);
	//Console.WriteLine("Размер переменной b1: {0}", sizeof(t));
}//SizeMethod

В этом примере операция применяется к трем встроенным типам - bool, double, char. Консольный вывод дает в качестве результата значения: 1, 8 и 2. Обращаю внимание на то, что аргументом операции может быть только имя типа. Попытка применить эту операцию к переменной t типа Type, имеющей значение System.Int32, приводит к ошибке компиляции.

Операция typeof, примененная к своему аргументу, возвращает его тип. И здесь в роли аргумента может выступать имя класса, как встроенного, так и созданного пользователем. Возвращаемый операцией результат имеет тип Type. К экземпляру класса применять операцию нельзя, но зато для экземпляра можно вызвать метод GetType, наследуемый всеми классами, и получить тот же результат, что дает typeof с именем данного класса. Такой альтернативный способ получения типа по экземпляру класса int показан в приведенном выше программном фрагменте. А сейчас я приведу фрагмент, где используется вызов операции typeof:

t = typeof(Class1);
Console.WriteLine("Тип класса Class1: {0}", t);
t = typeof(Testing);
Console.WriteLine("Тип класса Testing: {0}", t);

Как получить подробную информацию о классе?

Пожалуй, следует рассказать не только о том, как можно получить переменную типа Type, а и о том, что можно с этой переменной делать.

Этот и последующий раздел прерывают последовательное рассмотрение темы операций языка C#. Полагаю, понимание того, с какой целью выполняются те или иные операции, не менее важно, чем знание самой операции, и я не стал откладывать изложение этого материала на последующие лекции.

Можно ли, зная тип (класс), получить подробную информацию обо всех методах и полях класса? Ясно, что такая информация может быть весьма полезной, если класс поставлен сторонней фирмой. Оказывается, это сделать нетрудно. Вся необходимая информация содержится в метаданных, поставляемых вместе с классом. Процесс получения метаданных называется отражением ( reflection ). Об отражении и метаданных уже говорилось в первой вводной лекции, и эта тема будет обсуждаться и далее. А сейчас я приведу пример, демонстрирующий получение подробной информации о методах и полях класса. Первым делом следует упростить в проекте использование классов пространства имен Reflection, добавив в начало проекта предложение

using System.Reflection;

В класс Testing я добавил существенно расширенный вариант метода WhoIsWho, который уже появлялся в наших примерах. Вот текст новой версии этой процедуры:

/// <summary>
/// Подробная информация о классе объекта, его значении,
/// методах класса, всех членов класса
/// </summary>
/// <param name="name">имя объекта</param>
/// <param name="any">объект любого типа</param>
public void WhoIsWho(string name,object any)
{
	Type t = any.GetType();
	Console.WriteLine("Тип {0}: {1} , значение: {2}",
		name, any.GetType(), any.ToString());
	Console.WriteLine("Методы класса:");
	MethodInfo[] ClassMethods = t.GetMethods();
	foreach (MethodInfo curMethod in ClassMethods)
	{
		Console.WriteLine(curMethod);
	}
	Console.WriteLine("Все члены класса:");
	MemberInfo[] ClassMembers = t.GetMembers();
	foreach (MemberInfo curMember in ClassMembers)
	{
		Console.WriteLine(curMember.ToString());
	}			
}//WhoIsWho

Коротко прокомментирую эту процедуру. Вначале создается переменная t типа Type. Значением этой переменной будет тип аргумента, переданного в процедуру в качестве значения параметра any. Напомню, any имеет базовый тип object и потому метод может быть вызван с аргументом, роль которого может играть выражение любого типа. Далее вызываются методы переменной t - GetMethods() и GetMembers(). Эти методы соответственно возвращают в качестве значений массивы элементов классов MethodInfo и MemberInfo. Эти классы содержатся в пространстве имен Reflection, они хранят информацию в первом случае о методах класса, во втором - о полях и методах класса, заданного переменной t. В пространстве имен Reflection имеются и другие классы, чьи методы и свойства полезны для получения дополнительной информации об исследуемом классе. Но я не буду сейчас столь подробно развивать эту тему.

В процедуре Main дважды вызывается процедура WhoIsWho. В первом вызове ее аргументом является выражение типа int, во втором - сам объект ts, вызывающий метод:

ts.WhoIsWho("2+2", 2+2);
ts.WhoIsWho("ts", ts);

И класс int, и созданный в этом проекте класс Testing имеют довольно много методов. Имеют они и свойства. Процедура WhoIsWho выдаст подробную информацию обо всех элементах этих классов. Результаты консольного вывода, полученного при двух вызовах этой процедуры, показаны на рис. 6.2.

Информация о классах int и Testing, полученная в процедуре WhoIsWho

Рис. 6.2. Информация о классах int и Testing, полученная в процедуре WhoIsWho

Рассмотрим выводимую информацию о классах. Для созданного в проекте класса Testing отображается информация о полях и методах как собственных, так и наследуемых от общего родителя - класса Object. Заметьте, отображается информация только об открытых полях и методах класса, а поскольку поля нашего класса закрыты, то и информации о них нет.

Класс Int подробно обсуждался в предыдущей и в этой лекции. Все методы, которые могут вызывать переменные (объекты) класса Int, были уже рассмотрены. Тем не менее, из выводимой информации можно узнать и нечто новое, поскольку выдаются сведения и о статических полях и методах класса.

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >
Александр Галабудник
Александр Галабудник

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

Александра Гусева
Александра Гусева
Сергей Кузнецов
Сергей Кузнецов
Россия, Москва
Pavel Kuchugov
Pavel Kuchugov
Россия, Московский инженерно-физический институт, 2010