Чтение онлайн

ЖАНРЫ

Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:

1. bool Equals (object obj) — проверяет эквивалентность текущего объекта и объекта, переданного в качестве аргумента;

2. System.туре GetType — возвращает системный тип текущего объекта;

3. string Tostring — возвращает строку, связанную с объектом. Для арифметических типов возвращается значение, преобразованное в строку;

4. int GetHashCode — служит как хэш-функция в соответствующих алгоритмах поиска по ключу при хранении данных в хэш-таблицах.

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

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

Перейдем теперь к примерам, на которых будем объяснять дальнейшие вопросы, связанные с типами и классами, переменными и объектами. Начнем с вполне корректного в языке C# примера объявления переменных и присваивания им значений:

int x=11;

int v = new Int32;

v = 007;

string s1 = "Agent";

s1 = s1 + v.ToString +x.ToString;

В этом примере переменная х объявляется как обычная переменная типа int. в то же время для объявления переменной v того же типа int используется стиль, принятый для объектов. В объявлении применяется конструкция new и вызов конструктора класса. В операторе присваивания, записанном в последней строке фрагмента, для обеих переменных вызывается метод ToString, как это делается при работе с объектами. Этот метод, наследуемый от родительского класса Object, переопределенный в классе int, возвращает строку с записью целого. Сообщу еще, что класс int не только наследует методы родителя — класса Object, — но и дополнительно определяет метод СоmраreTо, выполняющий сравнение целых, и метод GetTypeCode, возвращающий системный код типа. Для класса int определены также статические методы и поля, о которых расскажу чуть позже.

Так что же такое после этого int, спросите Вы: тип или класс? Ведь ранее говорилось, что int относится к value-типам, следовательно, он хранит в стеке значения своих переменных, в то время как объекты должны задаваться ссылками. С другой стороны, создание экземпляра с помощью конструктора, вызов методов, наконец, существование родительского класса Object, — все это указывает на то, что int — это настоящий класс. Правильный ответ состоит в том, что int — это и тип, и класс. В зависимости от контекста х может восприниматься как переменная типа int или как объект класса int. Это же верно и для всех остальных value-типов. Замечу еще, что все значимые типы фактически реализованы как структуры, представляющие частный случай класса.

Остается понять, для чего в языке C# введена такая двойственность. Для int и других значимых типов сохранена концепция типа не только из-за ностальгических воспоминаний о типах. Дело в том, что значимые типы эффективнее в реализации, им проще отводить память, так что именно соображения эффективности реализации заставили авторов языка сохранить значимые типы. Более важно, что зачастую необходимо оперировать значениями, а не ссылками на них, хотя бы из-за различий в семантике присваивания для переменных ссылочных и значимых типов.

С другой стороны, в определенном контексте крайне полезно рассматривать переменные типа int как настоящие объекты и обращаться с ними как с объектами. В частности, полезно иметь возможность создавать и работать со списками, чьи элементы являются разнородными объектами, в том числе и принадлежащими к значимым типам.

Дальнейшие примеры работы с типами и проект Types

Обсуждение особенностей тех или иных конструкций языка невозможно без приведения

примеров. Для каждой лекции я строю один или несколько проектов, сохраняя по возможности одну и ту же схему и реально выполняя проекты в среде Visual Studio.Net. Для работы с примерами данной лекции построен консольный проект с именем Types, содержащий два класса: Class1 и Testing. Расскажу чуть подробнее о той схеме, по которой выстраиваются проекты. Класс Class1 строится автоматически при начальном создании проекта. Он содержит процедуру Main — точку входа в проект. В процедуре Main создается объект класса Testing и вызываются методы этого класса, тестирующие те или иные ситуации. Для решения специальных задач, помимо всегда создаваемого класса Testing, создаются один или несколько классов. Добавление нового класса в проект я осуществляю выбором пункта меню Project/Add Class. В этом случае автоматически строится заготовка для нового класса, содержащая конструктор без параметров. Дальнейшая работа над классом ведется над этой заготовкой.

Создаваемые таким образом классы хранятся в проекте в отдельных файлах. Это особенно удобно, если классы используются в разных проектах. Функционально связанную группу классов удобнее хранить в одном файле, что не возбраняется.

Все проекты в книге являются самодокументируемыми. Классы и их методы сопровождаются тегами <summary>. В результате появляются подсказки при вызове методов и возможность построения XML-отчета, играющего роль спецификации проекта.

Приведу текст класса Class1;

using System;

namespace Types

{

/// <summary>

/// Проект Types содержит примеры, иллюстрирующие работу

/// со встроенными скалярными типами языка С#.

/// Проект содержит классы: Testing, Class1.

///

/// </summary>

class Class1

{

/// <summary>

/// Точка входа проекта.

/// В ней создается объект класса Testing

/// и вызываются его методы.

/// </summary>

[STAThread]

static void Main

{

Testing tm = new Testing ;

Console.WriteLine("Testing.Who Test");

tm.WhoTest;

Console.WriteLine("Testing.Back Test");

tm.BackTest ;

Console.WriteLine("Testing.OLoad Test");

tm.OLoadTest ;

Console.WriteLine("Testing.ToString Test");

tm.ToStringTest ;

Console.WriteLine("Testing.FromString Test");

tm.FromStringTest ;

Console.WriteLine("Testing.CheckUncheck Test");

tm.CheckUncheckTest ;

}

}

}

Класс Class1 содержит точку входа Main и ничего более. В процедуре Main создается объект tm класса Testing, затем поочередно вызываются семь методов этого класса. Каждому вызову предшествует выдача соответствующего сообщения на консоль. Каждый метод — это отдельный пример, подлежащий обсуждению.

Семантика присваивания

Рассмотрим присваивание:

х = е.

Чтобы присваивание было допустимым, типы переменной х и выражения е должны быть согласованными. Пусть сущность х согласно объявлению принадлежит классу T. Будем говорить, что тип T основан на классе T и является базовым типом х, так что базовый тип определяется классом объявления. Пусть теперь в рассматриваемом нами присваивании выражение е связано с объектом типа Т1.

Поделиться с друзьями: