📄 chapter 4.mht
字号:
presents a unified=20
view of the type system where everyone is equal before the law as an =
object=20
type. A value type can also implement an interface, and boxing not only =
converts=20
a value type to object but also to any interface type implemented by the =
value=20
type. In other words, boxing creates an object and copies the values in =
the=20
value type to the ones in the object. <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">Conceptually, we can =
view a=20
boxing conversion as follows. Assuming we had a value type int and we =
want to=20
box this value or convert it into an object. We would internally declare =
a class=20
as follows.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U>a.cs</U><o:p></o:p></P>
<P class=3DCprg>class int_box<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>int x;<o:p></o:p></P>
<P class=3DCprg>public int_box(int t)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>x =3D t;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg>int i =3D 123;<o:p></o:p></P>
<P class=3DCprg>object b =3D i;<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">This=20
becomes<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg>int i =3D 123;<o:p></o:p></P>
<P class=3DCprg>object b =3D new int_box(i);<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">When we write the =
above lines,=20
internally the compiler can create a class that has any name. We have =
chosen=20
int_box as the name of the class. The above is conceptual, it may not =
happen the=20
way we've explained it. First, the compiler creates a new object that =
looks like=20
the class int_box. This has a constructor that accepts one parameter =
that simply=20
initializes the variable x, representing the value type int. Thus, we =
have now=20
converted an int into an object. Replace int with the data type you want =
to=20
promote it to, an Object and the above explanation then will hold=20
water.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U>a.cs</U><o:p></o:p></P>
<P class=3DCprg>class zzz <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static void Main()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>int i =3D 123;<o:p></o:p></P>
<P class=3DCprg>object b =3D i;<o:p></o:p></P>
<P class=3DCprg>if ( b is int)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true");<o:p></o:p></P>
<P class=3DCprg>if ( b is object)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true1");<o:p></o:p></P>
<P class=3DCprg>if ( b is long)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true2");<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>true<o:p></o:p></P>
<P class=3DCoutput>true1<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">The object b has a =
dual role to=20
perform.<SPAN style=3D"mso-spacerun: yes"> </SPAN>Thus, the above =
classes=20
are not created and in spite of b being an object it is now also an int. =
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U>a.cs</U><o:p></o:p></P>
<P class=3DCprg>class zzz <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static void Main()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>object b =3D =91a=92 ;<o:p></o:p></P>
<P class=3DCprg>if ( b is int)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true");<o:p></o:p></P>
<P class=3DCprg>if ( b is object)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true1");<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>true1<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">By default, an object =
is first=20
only an object and nothing else. In the previous program, we promoted =
int i to=20
become a reference type, hence the object b could either be treated as =
an object=20
or a value type int at the same time.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U>a.cs</U><o:p></o:p></P>
<P class=3DCprg>class zzz <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static void Main()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>int b =3D 11;<o:p></o:p></P>
<P class=3DCprg>if ( b is int)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true");<o:p></o:p></P>
<P class=3DCprg>if ( b is object)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("true1");<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>true<o:p></o:p></P>
<P class=3DCoutput>true1<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">Also, everyone is =
derived from=20
object. The earlier example demonstrates this point. =
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U>a.cs</U><o:p></o:p></P>
<P class=3DCprg>class zzz {<o:p></o:p></P>
<P class=3DCprg>public static void Main()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>xxx a =3D new xxx(1);<o:p></o:p></P>
<P class=3DCprg>object b =3D a;<o:p></o:p></P>
<P class=3DCprg>a.x =3D 2;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(((xxx)b).x);<o:p></o:p></P>
<P class=3DCprg>yyy c =3D new yyy(1);<o:p></o:p></P>
<P class=3DCprg>object d =3D c;<o:p></o:p></P>
<P class=3DCprg>c.x =3D 2;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(((yyy)d).x);<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>struct xxx<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public int x;<o:p></o:p></P>
<P class=3DCprg>public xxx(int i)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>x =3D i;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>class yyy {<o:p></o:p></P>
<P class=3DCprg>public int x;<o:p></o:p></P>
<P class=3DCprg>public yyy(int i)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>x =3D i;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>1<o:p></o:p></P>
<P class=3DCoutput>2<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">This is the =
single-most important=20
distinction between a class and a struct or between value types and =
reference=20
types. When we equate object b to value type a, we are creating a new =
copy of=20
the int in memory and initializing this new memory to the value of the=20
individual members of the struct. Thus, at the end of the statement, we =
now have=20
two identical structures in different areas of memory with no linkages =
between=20
the two. Changing the value of x from b does not change the value of x =
in a as=20
they are independent of each other. <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">However, with =
reference types,=20
things change a lot. We are not copying the object c but storing a =
number in d=20
that signifies where this object starts in memory. Hence, there is only =
one=20
object c in memory which can be accessed either using c or d. Thus =
changing in=20
one will reflect the change in the other.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">Unboxing is reversing =
the above=20
process, that is, converting an object type into value type. A check has =
to be=20
performed first whether the object can be converted to the value type. =
If the=20
check results true then the copy work into the value type should be =
initiated.=20
Referring to our earlier example, unboxing would read as. =
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg>object b =3D net int_box(1);<o:p></o:p></P>
<P class=3DCprg>int I =3D ((int_box)b).x;<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U><SPAN=20
style=3D"FONT-SIZE: 10pt; FONT-FAMILY: 'Bookman Old =
Style'">a.cs</SPAN></U><SPAN=20
style=3D"FONT-SIZE: 10pt; FONT-FAMILY: 'Bookman Old =
Style'"><o:p></o:p></SPAN></P>
<P class=3DCprg>class zzz <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static void Main()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>long f =3D 1;<o:p></o:p></P>
<P class=3DCprg>object b =3D f;<o:p></o:p></P>
<P class=3DCprg>int i =3D (int)b;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(i);<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Compiler Error</U><o:p></o:p></P>
<P class=3DCoutput>Exception occurred: System.InvalidCastException: An =
exception=20
of type System.InvalidCastException was thrown.<o:p></o:p></P>
<P class=3DCoutput><SPAN style=3D"mso-spacerun: yes"> =
</SPAN>at=20
zzz.Main()<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">A type cannot be =
unboxed to a new=20
type if it has been boxed earlier as this will throw an exception at run =
time.=20
However, it can be converted to the original. The language does a type =
check for=20
boxing and unboxing as the type must be the same. A run time type check =
is=20
carried out for unboxing operations. So think twice before you unbox.=20
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">In the above =
instance, we started=20
with a long. We boxed it to an object b that is not only an object but =
also a=20
long. We then tried to unbox this object into an int and not a long =
which causes=20
problems. <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCprg><U>a.cs</U><o:p></o:p></P>
<P class=3DCprg>class zzz <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static void Main()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>long f =3D 1;<o:p></o:p></P>
<P class=3DCprg>object b =3D f;<o:p></o:p></P>
<P class=3DCprg>long<SPAN style=3D"mso-spacerun: yes"> </SPAN>i =
=3D=20
b;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Compiler Error</U><o:p></o:p></P>
<P class=3DCoutput>a.cs(7,11): error CS0029: Cannot implicitly convert =
type=20
'object' to 'long'<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">We can convert an int =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -