1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 64
Текст из файла (страница 64)
В ы объявляете ии н и ц и а л и з и р у е т е п е р е м е н н ы е т и п о в - з н а ч е н и й , т а к и х к а к i n t и л и d o u b l e , следующимобразом:int п;n = 1;326////ОбъявлениеИнициализацияЧасть V. За базовыми классам»Однако с с ы л к и н а о б ъ е к т ы в ы о б ъ я в л я е т е и и н и ц и а л и з и р у е т е с о в е р ш е н н о и н а ч е :publicclasspublicintMyClassn;MyClass m c ;//mc = new M y C l a s s () ;П е р е м е н н а я mcОбъявление//Инициализацияи м е е т ссылочныйпоскольку она ссылаетсятип,напотенциально у д а л е н н у ю п а м я т ь . В с т р о е н н ы е п е р е м е н н ы е т и п а i n t и л и d o u b l e известныкакпеременныетипов-значений.Если в ы п о с м о т р и т е н а п и л и т с б о л е е п р и с т а л ь н о , т о у в и д и т е , ч т о е д и н с т в е н н о е реальное отличие с о с т о и т в т о м , ч т о С# в ы д е л я е т п а м я т ь д л я п е р е м е н н ы х т и п о в - з н а ч е н и йавтоматически, в т о в р е м я к а к д л я о б ъ е к т о в к л а с с о в в ы д о л ж н ы в ы д е л я т ь п а м я т ь я в н о .Интересно, нельзя л и о б ъ е д и н и т ь и х п о с р е д с т в о м н е к о т о р о й Е д и н о й Т е о р и и К л а с с о в ?Структуры С #С# определяет т р е т и й т и п п е р е м е н н ы х , и м е н у е м ы й структурой,к о т о р ы й представляет собой мост ч е р е з п р о п а с т ь м е ж д у с с ы л о ч н ы м и т и п а м и и т и п а м и - з н а ч е н и я м и .
Синтаксис объявления с т р у к т у р ы в ы г л я д и т п о ч т и т а к ж е , к а к и у к л а с с а :publicstructMyStructpublicintpublicdoublepublicclassn;d;MyClasspublicintpublicdoublen;d;Обращение к о б ъ е к т у с т р у к т у р ы о с у щ е с т в л я е т с я т а к ж е , к а к и к о б ъ е к т у к л а с с а , новыделение памяти — к а к д л я т и п а - з н а ч е н и я , ч т о д е м о н с т р и р у е т с я с л е д у ю щ и м к о д о м :// Объявлениеint П ;n = 1;идоступкпростомутипу-значению/ / Объявление с т р у к т у р ы п о х о ж е н а о б ъ я в л е н и е п р о с т о г о i n tMyStruct m s ;// Автоматическое выделение памятиms.n = 3 ;// Доступ к членам в ы п о л н я е т с я т а к же,как иins.d = 3 .
0 ;//дляобъектакласса// Память для объекта класса должна быть выделена в// отдельной области при помощи оператора newMyClass mc = n e w M y C l a s s ;men = 2 ;mc.d = 2 . 0 ;Объект s t r u c t х р а н и т с я в п а м я т и т а к ж е , к а к и п е р е м е н н ы е в с т р о е н н ы х т и п о в . Переменная ms не я в л я е т с я с с ы л к о й на н е к о т о р ы й б л о к в н е ш н е й п а м я т и , в ы д е л е н н ы й в отдельной области. О б ъ е к т ms з а н и м а е т п а м я т ь в т о й же о б л а с т и , ч т о и п е р е м е н н а я п, к а кпоказано на рис.
1 4 . 1 .km 14. Интерфейсы и структуры327Рис. 14.1. Структурная переменная ms "живет"в той же области памяти, что и переменная п,в то время как память для объекта тс выделяется в отдельной области памятиОтличие между ссылками и типами-значениями еще более очевидно в следующеепримере. Создание массива из 100 ссылочных объектов требует от программы 101 вызовоператора n e w (один для массива и по одному для каждого объекта):M y C l a s s [ ] mc = new M y C l a s s [ 1 0 0 ] ;f o r ( i n t i = 0; i < m s .
L e n g t h ; i + + ){mc [ i ] = new M y C l a s s ( ) ;}m c [ 0 ] . n = 0;Массив также приводит к определенным накладным расходам, как в смысле времеybработы, так и используемой памяти.Каждый элемент в массиве тс должен быть достаточно большим, чтобы содержать ссылку на объект.Каждый объект M y C l a s s имеет невидимые накладные расходы памяти до и послеединственного члена-данных п.При рассмотрении времени работы программы следует учесть, что она должна100 раз выделить область памяти, а обращение к элементу массива требует двухобращений к ссылкам — ссылке на массив и ссылке в соответствующем элементемассива.Память для объекта структуры выделяется сразу, как для части массива:// Объявлениеi n t [] i n t e g e r sintegers[0] =// ОбъявлениеM y S t r u c t [ ] msms [ 0] .
n = 0 ;массива i n t= new i n t [ 1 0 0 ] ;// Выделение0;массива структур такое же простое= new M y S t r u c t [ 1 0 0 ] ; // ВыделениепамятипамятиВ этом случае выделяется один большой блок памяти.328Часть V. За базовыми классамиКонструктор структурыИнтересно, что структура может быть инициализирована с использованием синтаксиса, применяемого для инициализации класса,public{structpublicpublicMyStructi n t n;doubled;}HyStruct m s = n e w M y S t r u c t ( ) ; / / И с п о л ь з о в а н и е n e wНесмотря на внешний вид, такая инициализация не приводит к выделению памятив отдельной области — она всего лишь обнуляет поля п и d.Вы можете создать собственный конструктор, выполняющий какие-то другие действия.
Рассмотрим следующий исходный текст:publicstructTest(;private i n t n;public T e s t ( i n tn){this.npublic=classn;Program{publicstaticvoidtestnewMain ( s t r i n g []args){Test=Test (10);Несмотря на свой внешний вид, объявление t e s t = n e w T e s t ( 1 0 ) ; не выделяет память, а только инициализирует уже выделенную память для типов-значений. Обратите внимание на использование круглых скобок, в отличие от массива, где скобки—квадратные.Методы структурСтруктура может иметь члены экземпляра, включая методы и свойства. Она можетиметь и статические члены. Статические члены структуры могут иметь инициализаторы,во нестатические члены (члены экземпляра) их иметь не могут.
Обычно объект структуры передается функции по значению, но может быть передан и по ссылке, если это специальным образом указывается в вызове функции с помощью ключевого слова r e f .Структура не может наследовать класс (отличный от O b j e c t , который будет описанпозже в данной главе) и не может наследоваться другими классами. Структура можетреализовывать интерфейс.Отличия между статическими членами и членами экземпляра описаны в главе 8, "Методы класса". В главе 7, "Функции функций", вы найдете информацию о передаче функции аргументов по значению и по ссылке. Наследованиерассматривается в главе 12, "Наследование".Гш 14.
Интерфейсы и структуры329Все классы (и структуры) наследуют один тип O b j e c t , сказано об этом явно или нет. Вы можете перекрывать методы O b j e c t . С практической точкизрения единственный метод, который вы можете захотеть перекрыть — этометод T o S t r i n g ( ) , позволяющий объекту создавать строковое представление информации о самом себе. Если вы не реализуете собственный методT o S t r i n g ( ) , то метод по умолчанию класса O b j e c t вернет полное имякласса, например M y N a m e s p a c e . M y C l a s s .
Обычно в этом мало толку.Пример применения структурыСледующая демонстрационная программа иллюстрирует различные возможности структур:// S t r u c t u r e E x a m p l e - демонстрация// структурного объектаusingSystem;usingSystem.Collections;namespaceразличныхсвойствStructureExample{publicstringinterfaceIDisplayableToString();/ / С т р у к т у р а можетpublic s t r u c t Testреализовывать интерфейс:IDisplayable{/ / С т р у к т у р а может и м е т ь ч л е н ы к а к о б ъ е к т а , т а к и// ( с т а т и ч е с к и е ) ; с т а т и ч е с к и е члены могут иметь// инициализаторыprivate int n;p r i v a t e s t a t i c double d = 2 0.0;/ / Для и н и ц и а л и з а ц и и ч л е н о в - д а н н ы х// использоваться конструкторpublic Test(int n){t h i s .
n = n;классас т р у к т у р ы может}// С т р у к т у р а может иметь// класса(статические)public int N{getsetpublicсвойствакакобъекта,таки{ r e t u r n n;}{ n = value;staticdoubleD{330Часть V. За базовыми классамиgetset{{r e t u r n d; }d = value; }}// С т р у к т у р а может и м е т ь методыp u b l i c v o i d C h a n g e M e t h o d ( i n t nNewValue,doubledNewValue){n = nNewValue;d = dNewValue;}// T o S t r i n g - перекрытие метода T o S t r i n g О и р е а л и з а ц и я// интерфейса I D i s p l a y a b l eoverride public string ToString(){return string.Format("({0:N},{l:N})'\ n, d ) ;publicclassProgram{publicstaticvoidMain(string[]args){// Создание объекта T e s tT e s t t e s t = new T e s t ( 1 0 ) ;Console.WriteLine("НачальноеOutputFunction(test);значениеtest");// Попытка модифицировать о б ъ е к т , п е р е д а в а я е г о в// качестве аргументаChangeValueFunction(test,100,200.0);C o n s o l e .