
Ответы_ТП
.pdf
следует, что если изменить значениеодной величины ссылочного типа, это может отразиться на другой (в данном слу чае, если изменить объект через ссылку с, объект b также изменит свое значение).
Рис. 1.2. Присваивание объектов
Аналогичная ситуация с операцией проверки на равенство . Величины значимого типа равны, если равны их значения. Величины ссылочного типа равны, если они ссылаются на одни и те же данные (на рисунке объекты b и с равны, но а не равно b даже при равенстве их значений или если они обе равны null).
39.Сбор мусора и использование диструктора
При использовании оператора new объектам динамически выделяется память из пула свободной памяти. Безусловно, объем буфера динамически выделяемой памяти не бесконечен. Следовательно, результат выполнения оператора new может быть неудачным из -за недостатка свободной памяти для создания желаемого объекта. Поэтому одним из ключевых компонентов схемы динамического выделения памяти является восстановление свободной памяти от неиспользуемых объектов, что позволяет делать ее доступной для создания последующих объектов. Во многих языках программирования освобождение ранее выделенной памяти выполняется вручную. Например, в C++для этого служит оператор delete. Однако в С# эта проблема решается по -другому, аименно с использованием системы сбора мусора.
Система сбора мусора С# автоматически возвращает память для повторного использования, действуя незаметно и без вмешательства
программиста. Ее работа заключается в следующем. Если не существует ни одной ссылки на объект, то предполага ется, что этот объект больше не нужен, и занимаемая им память освобождается.
Эту(восстановленную) память снова можно использовать для размещения другихобъектов.
Система сбора мусора действует только спорадически во время выполнения отдельной программы. Эта система может и бездействовать: она не "включается" лишьпотому, что существует один или несколько объектов, которые больше не используются в программе. Поскольку на сбор мусора требуется определенное время, динамическая система С# активизирует этот процес с только по необходимости или в специальных случаях. Таким образом, вы даже не будете знать, когда происходит сбор мусора, а когда — нет.
40.Свойство_ описание и назначение
Свойство — это специальный тип членов класса, который включает поле, и методы досту па к этому полю.Часто требуется создать поле, которое должно быть доступно для пользователей объекта,но программист при этом хочет осуществлять управление операциями, разрешенными к выполнению над этим полем. Например, по некоторым обстоятельствам вы желае те ограничить диапазон значений, которые можно присваивать этому полю. Несмотря на то, что этого можно достичь с помощью закрытой переменной и методов доступа к ней, свойство предлагает более удобный и простой способ решения этой задачи.
Свойства во многом напоминают индексаторы. Свойство состоит из имени и парыаксессоров(get и set).Аксессоры используются для чтения содержимого переменной и записи в нее нового значения. Основное достоинство свойства состоит в том,что его имя можно использовать в выражениях и инструкциях присваивания подобно обычной переменной, хотя в действительности здесь будут автоматически вызываться get- и set-аксессоры. Автоматический вызов аксессоров и роднит свойства с индексаторами.
Формат записи свойства таков:
ТИП ИМЯ{
get{
// код аксессора чтения поля
}
set{
// код аксессора записи поля
}
Здесь ТИП — это тип свойства ( например, i n t ) , а имя — его имя. После определения свойства любое использование его имени означает вызов соответствующего аксессора. Аксессорset автоматически принимает параметр с именем value, который содержит значение, присваиваемое свойству.
Свойства не определяют область памяти, они управляют доступом к полю, но самого поля не обеспечивает. Это поле должно быть задано независимо от свойства.
Пример, в котором определяется свойство myprop, используемое для доступа к полю prop. Это свойство позволяет присваивать полю только положительные числа.
// Пример использования свойства,
usingSystem;
classSimpProp {
intprop; // Это поле управляется свойс твом myprop.
publicSimpProp() { prop = 0 ; }
/* Это свойство поддерживает доступ к закрытой
переменной экземпляра prop. Оно позволяет
присваивать ей только положительные числа. */ publicintmyprop {
get {
return prop;
}
set {
if(value>= 0) prop = value;
}}
}
// Демонстрируем использование свойства, classPropertyDemo {
public static void Main() { SimpPropob = new SimpProp ();
Console.WriteLine(" Исходноезначение ob.myprop: " + ob.myprop);
ob.myprop = 100; // Присваиваемзначение .
Console.WriteLine(" Значениеob.myprop: " + ob.myprop);
//Переменной prop невозможно присвоить
//отрицательное значение.
Console.WriteLine(
"Попытка присвоить -10 свойству ob.myprop");
ob.myprop = -10;
Console.WriteLine(" Значениеob.myprop: " + ob.myprop);
}
}
Результаты выполнения этой программы выглядят так:
Исходное значение ob.myprop: 0
Значение ob.myprop: 100
Попытка присвоить -10 свойству ob.myprop
Значение ob.myprop: 100
Можно создавать свойства, предназначенные только для чтения (определив лишь get-аксессор ) либо только для записи (определив лишь set-аксессор).
На использование свойств налагаются ограничения. Во -первых, поскольку в свойстве не определяется область памяти, его нельзя передавать методу в качестве ref- или out-параметра . Во-вторых, свойство нельзя перегружать. (Но при необходимости вы можете иметь два различных свойства, которые используют одну и ту же базовую переменную, но к такой организации свойств прибегают нечасто.) Наконец, свойство не должно изменять состояние ба зовой переменной привызове get-аксессора, хотя несоблюдение этого правила компилятор обнаружить не всостоянии. Другими словами, get-операция должна быть максимально простой.
41.События_ описание и назначения
На основе делегатов построено еще одно важное с редство С#: событие (event). Событие — это по сути автоматическое уведомление о выполнении некоторого действия. События работают следующим образом. Объект, которому необходима информация онекотором событии, регистрирует обработчик для этого события. Когда ожидаемоесобытие происходит, вызываются все зарегистрированные
обработчики. А теперьвнимание: обработчики событий представляются делегатами.
События — это члены класса, которые объявляются с использованием ключевогослова event. Наиболее распространенная форма объявления события имеет следующий вид:
event событийный_делегат объект;
Здесь элемент событийный_делегат означает имя делегата, используемого дляподдержки объявляемого события, а элемент объект
— это имя создаваемого событийного объекта.
using System;
// Объявляем делегат для события,
delegate void MyEventHandler();
//Объявляемкласссобытия, class MyEvent {
public event MyEventHandler SomeEvent;
//Этот метод вызывается для генерирования события,
public void OnSomeEvent() { if(SomeEvent != null) SomeEvent();
}}
class EventDemo {
// Обработчиксобытия, static void handler() {
Console.WriteLine(" Произошлособытие .");
}
public static void Main() {
MyEvent evt = new MyEvent();
// Добавляем метод handler() в список события,
evt.SomeEvent += new MyEventHandler( handler);
// Генерируем событие,
evt.OnSomeEvent();
}}
При выполнении программа отображает следующие результаты:
Произошло событие.
Программа начинается с такого объявления делегата для обработчика события:
delegatevoidMyEventHandler();
Все события активизируются посредством делегата. Следовательно, событийный делегат определяет сигнатуру для события. В данном случае параметры отсутствуют, однако событийные параметры разрешены. Поскольку события обычно предназначены для многоадресатной передачи, они должны возвращать значение типа void.
Затем создается класс события MyEvent. При выполнении следующей строки кода, принадлежащей этому классу, объявляется событийный объект SomeEvent:
publiceventMyEventHandlerSomeEvent ;
Обратите внимание на синтаксис. Именно так объявляются события всех типов. Кроме того, внутри класса MyEvent объявляется метод OnSomeEvent(), который в этой программе вызывается, чтобы сигнализировать о событии. (Другими словами,этот метод вызывается, когда происходит событие.) К ак показано в следующем фрагменте кода, он вызывает обработчик события посредством делегата SomeEvent.
if(SomeEvent != null)
SomeEvent();
Обратите внимание на то, что обработчик события вызывается только в том случае, если делегат SomeEvent не равен null-значению. Поскольку другие части программы, чтобы получить уведомлении о событии, должны зарегистрироваться, можносделать так, чтобы метод OnSomeEvent() был вызван до регистрации любого обработчика события. Чтобы предотвратить вызов null-объекта, событийный делегат необходимо протестировать и убедиться в том, что он не равен null-
значению.
Внутри класса EventDemo создается обработчик события handler(). В этом примере обработчик события просто отображает сообщение, но ясно, что другие обработчики могли бы выполнять более полезные действия. Как показано в следующем фрагменте кода, в методе Main() создается объект класса MyEvent, а метод handler() регистрируется в качестве обработчика этого события.
MyEvent evt = new MyEvent();
// Добавляем метод handler() в список события,
evt.SomeEvent += new MyEventHandler(handler);
Обратите внимание на то, что обработчик добавляется в список с использованием составного оператора "+=". Следует отметить, что события поддерживают только операторы "+=" и " - = ". В нашем примере метод handler() является статическим, но в общем случае обработчики событий могут быть методами экземпляров классов. Наконец, при выполнении следующ ей инструкции "происходит" событие.
// Генерируем событие.
evt.OnSomeEvent();
При вызове метода OnSomeEvent() вызываются все зарегистрированные обработчики событий. В данном случае зарегистрирован только один обработчик, но их могло бы быть и
больше.
42.Структуры_ описание и назначение
Классы — это ссылочные типы. Это означает, что к объектамклассов доступ осуществляется через ссылку. Этим они отличаются от типов значений, к которым в С# реализован прямой доступ. Но иногда желательно получатьпрямой доступ и к объектам, как
вслучае нессылочных типов. Одна из причин дляэтого — эффективность. Ведь очевидно, что доступ к объектам классов через ссылкиувеличивает расходы системных ресурсов, в том числе и памяти. Даже для очень маленьких объектов требуются существенные объемы памяти. Для компенсации упомянутых расходов времени и пространства
вС# предусмотрены структуры. Структура подобна классу, но она относится к типу значений, а не к ссылочны м типам.
Структуры объявляются с использованием ключевого слова struct и синтаксически подобны классам. Формат записи структуры таков:
struct имя : интерфейсы {
// объявления членов
}
Элемент имя означает имя структуры.
Структуры не могут наследовать други е структуры или классы. Структуры не могут использоваться в качестве базовых для других структур или классов. (Однако, подобно другим С#-типам, структуры наследуют класс object). Структура может реализовать один или несколько интерфейсов. Они указываются п осле имени структуры и отделяются запятыми. Как и у классов, членами структур могут быть методы, поля, индексаторы, свойства, операторные методы и события. Структуры могут также определять конструкторы, но не деструкторы. Однако для структуры нельзя опреде лить конструктор по умолчанию (без параметров). Дело в том, что конструктор по умолчанию автоматически определяется для всех структур, и его изменить нельзя. Поскольку структуры не поддерживают наследования, члены структуры
нельзя определять с использовани ем модификаторов abstract , virtual
или protected.
Объект структуры можно создать с помощью оператора new, подобно любому объекту класса, но это не обязательно. Если использовать оператор new, вызывается указанный конструктор, а если не использовать его, об ъект все равно будет создан, но не инициализирован. В этом случае вам придется выполнить инициализацию вручную, рассмотрим пример использования структуры для хранения информации о книге.
/ / Демонстрация использования структуры.
using System;
//Определениеструктуры , struct Book {
public string author; public string title; public int copyright;
public Book(string a, string t, int c) { author = a;
title = t; copyright = c;
}}
//Демонстрируем использование структуры Book, classStructDemo {
public static void Main() {
Book book1 = new Book("Herb Schildt","C# A Beginner's Guide",2001);
// Вызов явно заданного конструктора.