C o n s o l e . R e a d ( ) ;
}
// C h a n g e V a l u e F u n c t i o n - п е р е д а ч а с т р у к т у р ы |
по |
значению j |
p u b l i c s t a t i c v o i d C h a n g e V a l u e F u n c t i o n ( T e s t |
t , |
|
i n t n e w V a l u e , d o u b l e |
dNewValue) |
{
t . N = |
newValue,- |
|
|
T e s t . D = d N e w V a l u e ; |
|
|
} |
|
|
|
// C h a n g e R e f e r e n c e F u n c t i o n - п е р е д а ч а с т р у к т у р ы по |
/ / с с ы л к е |
|
|
p u b l i c |
s t a t i c v o i d C h a n g e R e f e r e n c e F u n c t i o n ( r e f T e s t t , |
|
i n t n e w V a l u e , |
d o u b l e dNewValue) |
{ |
|
|
|
t . N = n e w V a l u e ; |
|
|
T e s t . D = dNewValue; |
|
|
} |
|
|
|
// O u t p u t F u n c t i o n - вывод информации об |
о б ъ е к т е , |
который |
/ / р е а л и з у е т м е т о д T o S t r i n g ( ) |
|
|
p u b l i c s t a t i c v o i d O u t p u t F u n c t i o n ( I D i s p l a y a b l e i d ) |
{ |
|
|
|
C o n s o l e . W r i t e L i n e ( " i d = { o } " , i d . T o S t r i n g ( ) ) ; |
|
} } |
|
|
|
} |
|
|
|
Программа |
S t r u c t u r e E x a m p l e сначала определяет |
интерфейс |
IDisplayableJ |
а затем простую структуру T e s t , которая реализует этот интерфейс. T e s t также опре- деляет два члена — член экземпляра п и статический член d. Статический инициализа- тор устанавливает член d равным 20; инициализатор для члена п не разрешен.
Структура T e s t определяет конструктор, свойство экземпляра N и статическое свой
ство D. |
|
T e s t также определяет собственный метод C h a n g e M e t h o d () |
и перекрывает метод! |
T o S t r i n g ( ) . Предоставлением метода T o S t r i n g () структура |
T e s t реализует ин- |
терфейс I D i s p l a y a b l e . |
|
Функция Main () создает объект t e s t вне локальной памяти и использует конструктор для инициализации выделенной ему памяти. Затем M a i n () вызывает функцию Out- p u t F u n c t i o n () для вывода объекта.
Далее функция Main () вызывает функцию C h a n g e V a l u e F u n c t i o n ( ) , передавая ей t e s t с двумя числовыми константами. Функция C h a n g e V a l u e F u n c t i o n () при сваивает эти значения членам п и d структуры T e s t . После возврата из функции C h a n g e V a l u e F u n c t i o n () вызывается функция O u t p u t F u n c t i o n ( ) , которая по зволяет убедиться, что значение d изменилось, а значение п — нет.
Вызов C h a n g e V a l u e F u n c t i o n () получает объект t e s t по значению, так что объ ект t в теле этой функции представляет собой копию исходного объекта t e s t , а не сам объект. Таким образом, присваивание t. N изменяет локальную копию и никак не влияет на объект t e s t e функции M a i n ( ) . Однако все объекты структуры T e s t совместно ис-
332 Часть V. За базовыми классам»
пользуют статический член d, так что присваивание T e s t . D изменяет d для всех объек тов, включая t e s t .
Следующей вызывается функция ChangeRef e r e n c e F u n c t i o n ( ) , которая выгля дит в точности как и функция C h a n g e V a l u e F u n c t i o n ( ) , за исключением использо вания в списке аргументов ключевого слова r e f . Это ключевое слово обеспечивает пе редачу объекта t e s t e функцию по ссылке, так что объект t в функции является ссыл кой на исходный объект t e s t , а не вновь созданной копией.
Последним вызовом в M a i n () является вызов метода C h a n g e M e t h o d ( ) , всегда ис пользующий передачу текущего объекта по ссылке, поэтому изменения, сделанные при вызове этого метода, сохраняются при возврате в Main ( ) .
Вывод программы имеет следующий вид:
|
|
|
|
|
|
Начальное з н а ч е н и е |
t e s t |
|
id = ( 1 0 . 0 0 , 2 0 . 0 0 ) |
|
|
Значение |
t e s t |
п о с л е |
в ы з о в а |
C h a n g e V a l u e F u n c t i o n ( 1 0 0 , 2 0 0 . 0 ) |
id = ( 1 0 . 0 0 , 2 0 0 . 0 0 ) |
|
|
Значение |
t e s t |
п о с л е |
в ы з о в а |
C h a n g e R e f e r e n c e F u n c t i o n ( 1 0 0 , 2 0 0 . 0 ) |
id = ( 1 0 0 . 0 0 , 2 0 0 . 0 0 ) |
|
Значение |
t e s t |
п о с л е |
в ы з о в а |
C h a n g e M e t h o d ( 1 0 0 0 , 2 0 0 0 . 0 ) |
id = (1,000 . 00 , |
2 , 000 . 00) |
|
Нажмите |
< E n t e r > |
д л я |
з а в е р ш е н и я п р о г р а м м ы . . . |
Структуры и классы имеют одну общую черту: и те и другие порождены из класса Object, указано ли это явно или нет. Этот факт унифицирует различные типы перемен ных в одну всеобъемлющую иерархию классов.
Предопределенные типы структур
Схожесть структур и простых типов-значений не только внешняя. В действительно
сти простые типы-значения являются структурами. |
Например, |
i n t — |
просто |
другое |
имя структуры I n t 3 2 , d o u b l e — другое имя |
структуры |
D o u b l e |
и так |
далее. |
В табл. 14.1 приведен полный список типов и соответствующих имен структур. |
|
Таблица 14.1. Имена структур для встроенных типов-значений
Имя типа |
Имя структуры |
|
|
bool |
Boolea n |
byte |
Byte |
sbyte |
SByte |
char |
Char |
decimal |
Decimal |
double |
Double |
float |
S i n g l e |
int |
I n t 3 2 |
uint |
UInt32 |
Глава 14. Интерфейсы и структуры |
333 |
Окончание табл. HI
Тип s t r i n g является ссылочным, а не типом-значением, поэтому для негоне существует соответствующей структуры. Вместо этого тип s t r i n g соответст вует классу S t r i n g . Тип s t r i n g в С# особенный и обладает рядом свойств, присущих структурам. Более детально он рассматривается в главе 9, "Работаю строками в С#".
Унификация системы типов с помощью структур
Тип i n t — другое имя для I n t 3 2 . Поскольку все структуры порождены от класса O b j e c t , i n t также не должен быть исключением. Это приводит к очень интересным результатам, которые демонстрирует приведенная ниже программа.
// T y p e U n i f i c a t i o n - д е м о н с т р а ц и я т о г о , ч т о i n t и I n t 3 2 в
// д е й с т в и т е л ь н о с т и |
|
одно |
и |
то же, |
и ч т о |
они порождены от |
/ / к л а с с а O b j e c t |
|
|
|
|
|
|
|
|
|
|
u s i n g S y s t e m ; |
|
|
|
|
|
|
|
|
|
|
|
n a m e s p a c e T y p e U n i f i c a t i o n |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p u b l i c |
c l a s s |
P r o g r a m |
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p u b l i c |
s t a t i c v o i d M a i n ( s t r i n g [ ] |
a r g s ) |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/ / |
С о з д а е м i n t |
и и н и ц и а л и з и р у е м |
е г о |
нулем |
|
|
i n t |
i |
= |
new |
i n t ( ) ; |
/ / Д а , |
т а к |
можно |
д е л а т ь |
|
// |
П р и с в а и в а е м |
ему |
з н а ч е н и е |
1 и |
выводим при |
помощи |
/ / и н т е р ф е й с а I F o r m a t t a b l e , к о т о р ы й р е а л и з у е т I n t 3 2 |
i |
= |
1; |
|
|
|
|
|
|
|
|
|
|
|
|
O u t p u t F u n c t i o n ( i ) ; |
|
|
|
|
|
|
|
|
II |
К о н с т а н т а |
2 |
также |
р е а л и з у е т |
I F o r m a t t a b l e |
|
O u t p u t F u n c t i o n ( 2 ) ; |
|
|
|
|
|
|
|
|
// |
В д е й с т в и т е л ь н о с т и |
вы можете |
даже |
в ы з в а т ь |
м е т о д |
/ / к о н с т а н т ы |
|
|
|
|
|
|
|
|
|
|
C o n s o l e . W r i t e L i n e ( " Н е п о с р е д с т в е н н ы й |
вывод |
= |
{ о } " , |
|
|
|
|
|
|
|
3 . T o S t r i n g ( ) ) ; |
|
|
|
|
|
// |
Это |
может |
быть |
п о л е з н ы м , |
н а п р и м е р , |
д л я |
выбора |
/ / ц е л о г о з н а ч е н и я и з с п и с к а : |
|
|
|
|
|
334 |
Часть V. За базовыми классами |
C o n s o l e . W r i t e L i n e ( " \ п В ы б и р а е м и з с п и с к а ц е л ы е " ) ;
o b j e c t [ ] o b j e c t s |
= |
new o b j e c t [ 5 ] ; |
|
o b j e c t s [ 0 ] |
= " э т о с т р о к а " ; |
|
o b j e c t s [ 1 ] = 2; |
|
|
|
|
o b j e c t s [ 2 ] |
= |
new |
P r o g r a m ( ) ; |
|
o b j e c t s [ 3 ] = 4; |
|
|
|
|
o b j e c t s [ 4 ] = 5 . 5 ; |
|
|
|
|
f o r ( i n t i n d e x = 0 ; i n d e x < o b j e c t s . L e n g t h ; i n d e x + + ) |
{ |
|
|
|
|
|
|
|
|
i f ( o b j e c t s [ i n d e x ] |
i s |
i n t ) |
|
|
{ |
|
|
|
|
|
|
|
i n t n = ( i n t ) o b j e c t s [ i n d e x ] ; |
|
|
C o n s o l e . W r i t e L i n e ( " Э л е м е н т { о } — { l } " , i n d e x , n ) ; |
|
} |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// |
Унификация |
т и п о в |
п о з в о л я е т в ы в о д и т ь |
т и п ы - з н а ч е н и я и |
// с с ы л к и , не р а з л и ч а я их |
|
C o n s o l e . W r i t e L i n e ( " \ п В ы в о д в с е х о б ъ е к т о в и з с п и с к а " ) ; |
i n t n C o u n t = 0; |
|
|
|
|
f o r e a c h ( o b j e c t |
о |
i n o b j e c t s ) |
|
{ |
|
|
|
|
|
|
|
|
C o n s o l e . W r i t e L i n e ( " O b j e c t s [ { o } ] - < { l } > " , |
|
n C o u n t + + , o . T o S t r i n g ( ) ) ; |
|
} |
|
|
|
|
|
|
|
// |
Ожидаем |
п о д т в е р ж д е н и я |
п о л ь з о в а т е л я |
|
C o n s o l e . W r i t e L i n e ( " Н а ж м и т е < E n t e r > д л я " + |
|
|
|
|
" з а в е р ш е н и я п р о г р а м м ы . . . " ) ; |
C o n s o l e . R e a d ( ) ; |
|
|
|
|
// O u t p u t F u n c t i o n |
- вывод |
п р о и з в о л ь н о г о |
о б ъ е к т а , |
// реализующего |
T o S t r i n g () |
|
|
p u b l i c s t a t i c v o i d O u t p u t F u n c t i o n ( I F o r m a t t a b l e i d )
C o n s o l e . W r i t e L i n e ( " З н а ч е н и е и з O u t p u t F u n c t i o n = { о } " , i d . T o S t r i n g ( ) ) ;
}
// T o S t r i n g - п р о с т а я o v e r r i d e p u b l i c s t r i n g
с т р о к о в а я функция T o S t r i n g ( )
{
r e t u r n " T y p e U n i f i c a t i o n P r o g r a m " ;
Функция Main () начинается с создания объекта i типа i n t . В ней используется конструктор по умолчанию I n t 3 2 О (можно просто написать i n t О ) , который ини циализирует переменную i нулевым значением. Далее программа присваивает перемен ной i значение 1. Это несколько отличается от формата, используемого при создании структуры.
Глава 14. Интерфейсы и структуры |
335 |
Функция Main () передает переменную i функции O u t p u t F u n c t i o n (), которая явлена как принимающая объект, реализующий интерфейс I F o r m a t t a b l e . Интерфейсом I F o r m a t t a b l e похож на интерфейс I D i s p l a y a b l e , который определялся в других про граммах. Единственным методом интерфейса I F o r m a t t a b l e является метод ToStrirqj Функция O u t p u t F u n c t i o n () выводит объект I F o r m a t t a b l e с использование строки, возвращаемой его методом T o S t r i n g ( ) . У переменной I n t 3 2 , которая реал зует этот метод, не возникает никаких проблем. Но самое интересное, что никаких про блем не возникает и при вызове O u t p u t F u n c t i o n ( 2 ) . Поскольку константа 2 имеет тип I n t 3 2 , она также реализует интерфейс I F o r m a t t a b l e . И наконец, фунция
|
|
|
|
Main () |
вызывает 3. T o S t r i n g () непосредственно. Вывод этой части функции |
Main () |
имеет следующий вид: |
З н а ч е н и е |
из |
O u t p u t F u n c t i o n = 1 |
З н а ч е н и е |
из |
O u t p u t F u n c t i o n = 2 |
Н е п о с р е д с т в е н н ы й вывод = 3
Далее функция Main() объявляет массив объектов типа O b j e c t и сохраняет в первом элементе массива s t r i n g , во втором— i n t , в третьем— экземпляр класса Program и т.д. Все это можно сделать, так как S t r i n g , I n t 3 2 и P r o g r a m порождены от Object.Итак массив внутри класса P r o g r a m хранит экземпляр P r o g r a m — правда, это интересно?
Затем программа проходит по всем элементам массива. Функция Main() мо жет выбрать из него все целые числа, запрашивая каждый объект, ЯВЛЯЕТСЯ ли он I n t 3 2 с помощью ключевого слова i s . Вывод этой части программы выглядит следующим образом:
Выбираем и з с п и с к а целые
Элемент |
1 — 2 |
Элемент |
3 — 4 |
Программа завершается демонстрацией использования того факта, что все подклассы Obj e c t — т.е. все классы — реализуют метод T o S t r i n g ( ) . Таким образом, чтобы вы вести все члены массива объектов, вам не надо беспокоиться об их типах. Функция M a i n () просто вновь проходит по массиву, вызывая метод T o S t r i n g () для каждого его элемента. В результате программа выводит на экран следующую информацию:
Вывод |
в с е х |
о б ъ е к т о в |
и з |
с п и с к а |
|
|
|
|
O b j e c t s |
[0] |
- |
о т о |
с т р о к а > |
|
|
|
|
O b j e c t s [ 1 ] |
- |
<2> |
|
|
|
|
|
|
|
|
O b j e c t s [ 2 ] |
- < T y p e U n i f i c a t i o n P r o g r a m > |
|
|
O b j e c t s [ 3 ] |
- |
<4> |
|
|
|
|
|
|
|
|
O b j e c t s [ 4 ] |
- < 5 . 5 > |
|
|
|
|
|
|
|
Нажмите |
< E n t e r > |
д л я |
з а в е р ш е н и я |
п р о г р а м м ы . . . |
|
|
Для |
класса P r o g r a m |
реализован тривиальный |
метод T o S t r i n g ( ) , просто чтобы |
показать, как это работает. |
|
|
|
|
|
|
|
|
Свойство T o S t r i n g ( ) , несомненно, поясняет |
магию функции |
Console. |
|
|
W r i t e ( ) . Честно говоря, даже не смотря исходный текст, можно |
поспорить, |
|
|
что W r i t e () |
принимает аргументы как принадлежащие типу O b j e c t . Затем |
|
|
она |
просто вызывает |
метод T o S t r i n g () |
для получения выводимой строки, |
|
|
которая |
подставляется вместо |
соответствующего |
элемента форматирования |
|
|
{п} |
в первой строке. |
|
|
|
|
|
336 |
Часть V. За базовыми классами |