Net framework 5, а также среды Visual Studio 2012 и C#


Упаковка.и.распаковка.значимых.типов ‰ Приведение



Download 6,27 Mb.
Pdf ko'rish
bet120/658
Sana12.06.2023
Hajmi6,27 Mb.
#950840
1   ...   116   117   118   119   120   121   122   123   ...   658
Bog'liq
CLR via C Programmirovanie na platforme Microsoft NET Framework 4 5 na yazyke C

169
Упаковка.и.распаковка.значимых.типов
‰
Приведение
типа
к
Point.
Когда выполняется приведение 
c
к типу 
Point
, объ-
ект в куче, на который указывает 
c
, распаковывается, и его поля копируются из 
кучи в 
p2
, экземпляр типа 
Point
, находящийся в стеке.
Понимаю, что вся эта информация о ссылочных и значимых типах, упаковке 
и распаковке поначалу выглядит устрашающе. И все же любой разработчик, стре-
мящийся к долгосрочному успеху на ниве .NET Framework, должен хорошо усвоить 
эти понятия — только так можно научиться быстро и легко создавать эффективные 
приложения.
изменение полей в упакованных значимых 
типах посредством интерфейсов (и почему 
этого лучше не делать)
Посмотрим, насколько хорошо вы усвоили тему значимых типов, упаковки и распа-
ковки. Взгляните на следующий пример: можете ли вы сказать, что будет выведено 
на консоль в следующем случае.
using System;
// Point - значимый тип.
internal struct Point {
private Int32 m_x, m_y;
public Point(Int32 x, Int32 y) {
m_x = x;
m_y = y;
}
public void Change(Int32 x, Int32 y) {
m_x = x; m_y = y;
}
public override String ToString() {
return String.Format("({0}, {1})", m_x.ToString(), m_y.ToString());
}
}
public sealed class Program {
public static void Main() {
Point p = new Point(1, 1);
Console.WriteLine(p);
p.Change(2, 2);
Console.WriteLine(p);
Object o = p;
продолжение



170
Глава.5 .Примитивные,.ссылочные.и.значимые.типы
Console.WriteLine(o);
((P
oint) o).Change(3, 3);
Console.WriteLine(o);
}
}
Все просто: 
Main
создает в стеке экземпляр 
p
типа 
Point
и устанавливает его поля 
m_x
и 
m_y
равными 1. Затем 
p
пакуется до первого обращения к методу 
WriteLine

который вызывает 
ToString
для упакованного типа 
Point
, в результате выводится, 
как и ожидалось, 
(1

1)
. Затем 
p
применяется для вызова метода 
Change
, который 
изменяет значения полей 
m_x
и 
m_y
объекта 
p
в стеке на 2. При втором обращении 
к 
WriteLine
, как и предполагалось, выводится 
(2

2)
.
Далее 
p
упаковывается в третий раз — 
o
ссылается на упакованный объект типа 
Point
. При третьем обращении к 
WriteLine
снова выводится 
(2

2)
, что опять 
вполне ожидаемо. И наконец, я обращаюсь к методу 
Change
для изменения полей 
в упакованном объекте типа 
Point
. Между тем 
Object
(тип переменной 
o
) ничего 
не «знает» о методе 
Change
, так что сначала нужно привести 
o
к 
Point
. При таком 
приведении типа 
o
распаковывается, и поля упакованного объекта типа 
Point
копируются во временный объект типа 
Point
в стеке потока. Поля 
m_x
и 
m_y
этого 
временного объекта устанавливаются равными 3, но это обращение к 
Change
не 
влияет на упакованный объект 
Point
. При обращении к 
WriteLine
снова выводится 
(2

2)
. Для многих разработчиков это оказывается неожиданным.
Некоторые языки, например C++/CLI, позволяют изменять поля в упакованном 
значимом типе, но только не C#. Однако и C# можно обмануть, применив интер-
фейс. Вот модифицированная версия предыдущего кода:
using System; 
// Интерфейс, определяющий метод Change
internal interface IChangeBoxedPoint { 
void Change(Int32 x, Int32 y); 
}
// Point - значимый тип
internal struct Point : IChangeBoxedPoint { 
private Int32 m_x, m_y; 
public Point(Int32 x, Int32 y) { 
m_x = x; 
m_y = y; 

public void Change(Int32 x, Int32 y) { 
m_x = x; m_y = y; 
}
public override String ToString() { 
return String.Format("({0}, {1})", m_x.To_String(), m_y.ToString()); 


171
Упаковка.и.распаковка.значимых.типов

}
public sealed class Program {
public static void Main() {
Point p = new Point(1, 1);
Console.WriteLine(p);
p.Change(2, 2); 
Console.WriteLine(p); 
Object o = p;
Console.WriteLine(o);
((Point) o).Change(3, 3);
Console.WriteLine(o);
// p упаковывается, упакованный объект изменяется и освобождается
((IChangeBoxedPoint) p).Change(4, 4); 
Console.WriteLine(p); 
// Упакованный объект изменяется и выводится 
((IChangeBoxedPoint) o).Change(5, 5); 
Console.WriteLine(o); 


Этот код практически совпадает с предыдущим. Основное отличие заключается 
в том, что метод 
Change
определяется интерфейсом 
IChangeBoxedPoint
и теперь тип 
Point
реализует этот интерфейс. Внутри 
Main
первые четыре вызова 
WriteLine
те 
же самые и выводят те же результаты (что и следовало ожидать). Однако в конец 
Main
я добавил пару примеров.
В первом примере 
p
— неупакованный объект типа 
Point
— приводится к типу 
IChangeBoxedPoint
. Такое приведение типа вызывает упаковку 
p
. Метод 
Change
вызывается для упакованного значения, и его поля 
m_x
и 
m_y
становятся равными 4, 
но при возврате из 
Change
упакованный объект немедленно становится доступным 
для уборки мусора. Так что при пятом обращении к 
WriteLine
на экран выводится 
(2

2)
, что для многих неожиданно.
В последнем примере упакованный тип 
Point
, на который ссылается 
o
, при-
водится к типу 
IChangeBoxedPoint
. Упаковка здесь не производится, поскольку 
тип 
o
уже упакован. Затем вызывается метод 
Change
, который изменяет поля 
m_x
и 
m_y
упакованного типа 
Point
. Интерфейсный метод 
Change
позволил мне изме-
нить поля упакованного объекта типа 
Point
! Теперь при обращении к 
WriteLine
выводится 
(5

5)
. Я привел эти примеры, чтобы продемонстрировать, как метод 
интерфейса может изменить поля в упакованном значимом типе. В C# сделать это 
без интерфейсов нельзя.



Download 6,27 Mb.

Do'stlaringiz bilan baham:
1   ...   116   117   118   119   120   121   122   123   ...   658




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish