📄 chapter 7.mht
字号:
all that we=20
receive is a warning. The object c is an instance of xxx and not yyy. =
There is=20
no way for the compiler to convert a xxx object into a yyy object. The =
warning=20
illustrates the wisdom of the compiler.<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 yyy<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 xxx<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static explicit operator yyy (xxx =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return new yyy();<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 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>xxx c =3D new xxx();<o:p></o:p></P>
<P class=3DCprg>if (c is yyy)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("yyy " + c);<o:p></o:p></P>
<P class=3DCprg>else<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("false " + c);<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 Warning</U><o:p></o:p></P>
<P class=3DCoutput>a.cs(17,5): warning CS0184: The given expression is =
never of=20
the provided ('yyy') type<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>false xxx<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">In this program, we =
thought the=20
explicit operator introduced would convert c, an xxx object to yyy. We =
pleaded=20
hard enough but it just did not help. We replaced the explicit modifier =
with=20
implicit but the compiler as adamant it is, refused to convert the xxx =
object=20
into a yyy object. We should have read the warning more=20
carefully.<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 yyy<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 xxx<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator yyy (xxx =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("operator");<o:p></o:p></P>
<P class=3DCprg>return new yyy();<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 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>zzz a =3D new zzz();<o:p></o:p></P>
<P class=3DCprg>xxx c =3D new xxx();<o:p></o:p></P>
<P class=3DCprg>a.abc(c);<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>public void abc(yyy o)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>if (o is yyy)<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("yyy " + o);<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 Warning</U><o:p></o:p></P>
<P class=3DCoutput>a.cs(21,5): warning CS0183: The given expression is =
always of=20
the provided ('yyy') type<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>operator<o:p></o:p></P>
<P class=3DCoutput>yyy yyy<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 now reverted to =
our earlier=20
program where we passed the object as a type yyy class, yet the compiler =
gives=20
us the same old warning. The compiler can convert an xxx to a yyy thanks =
to the=20
operator. If we change the parameter in abc from class yyy to object, =
the is=20
will<SPAN style=3D"mso-spacerun: yes"> </SPAN>still be =
false.=20
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">The return value of =
an is=20
operator notifies whether the object can be converted to a particular =
data type=20
or not. The datatype follows the is operator whereas the object precedes =
it.<SPAN style=3D"mso-spacerun: yes"> </SPAN>The is operator =
ignores user=20
defined conversions and only looks at reference conversions. It can be =
used with=20
value and reference types.<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><B><SPAN=20
style=3D"FONT-SIZE: 14pt; COLOR: windowtext; FONT-FAMILY: Tahoma">The as =
operator<o:p></o:p></SPAN></B></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>string s;<o:p></o:p></P>
<P class=3DCprg>s =3D<SPAN style=3D"mso-spacerun: yes"> =
</SPAN>"hi" as=20
string;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(s);<o:p></o:p></P>
<P class=3DCprg>s =3D<SPAN style=3D"mso-spacerun: yes"> </SPAN>100 =
as=20
string;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(s);<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(8,6): error CS0039: Cannot convert type 'int' to =
'string'=20
via a built-in conversion<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 as operator =
behaves like a=20
cast. It converts one data type into another. Thus in the first case, it =
converts "hi" into a string. As hi can be converted to a string, the =
value of s=20
is hi. However, a 100 cannot be converted into a string and thus we get =
an=20
error. A cast normally throws an exception whereas the as operator =
returns a=20
error. <o:p></o:p></SPAN></P>
<P class=3DCprg><SPAN style=3D"FONT-SIZE: 10pt; FONT-FAMILY: 'Bookman =
Old Style'"><![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>int i =3D 100 as int;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></P>
<P class=3DCprg><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></P>
<P class=3DCoutput><U>Compiler Error</U><o:p></o:p></P>
<P class=3DCoutput>a.cs(4,9): error CS0077: The as operator must be used =
with a=20
reference type ('int' is a value type)<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 error message for =
once makes=20
it very clear that the as operator does not accept a value type like int =
but=20
requires reference types like string. The earlier rules on user supplied =
conversions et all apply verbatim here also.<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><B><SPAN=20
style=3D"FONT-SIZE: 14pt; COLOR: windowtext; FONT-FAMILY: Tahoma">The =
Conditional=20
Operator<o:p></o:p></SPAN></B></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>int i =3D 10;<o:p></o:p></P>
<P class=3DCprg>string<SPAN style=3D"mso-spacerun: yes"> =20
</SPAN>j;<o:p></o:p></P>
<P class=3DCprg>j =3D i >=3D 20 ? "hi" : "bye";<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(j);<o:p></o:p></P>
<P class=3DCprg>j =3D i >=3D 2 ? "hi" : "bye";<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(j);<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>bye<o:p></o:p></P>
<P class=3DCoutput>hi<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 conditional =
operator is also=20
called the ternary operator as it takes three operands. The first is the =
condition to be checked. If it results in true then the answer lies =
between the=20
? and :. If it evaluates to false, the answer is within the : to the =
semi colon.=20
Thus the ? : operator operates like an if else on one line. As the C =
programming=20
language offered us this operator and C++ followed suit, then how could =
C#=20
refuse. It is available but use it at your own =
risk.<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>int i =3D 10;<o:p></o:p></P>
<P class=3DCprg>string<SPAN style=3D"mso-spacerun: yes"> =20
</SPAN>j;<o:p></o:p></P>
<P class=3DCprg>j =3D i >=3D 20 ? 7 > 3 ? "no"<SPAN=20
style=3D"mso-spacerun: yes"> </SPAN>: "bye" : "yes" =
;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(j);<o:p></o:p></P>
<P class=3DCprg>j =3D i >=3D 20 ? 7 < 3 ? "no"<SPAN=20
style=3D"mso-spacerun: yes"> </SPAN>: "bye" : "yes" =
;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(j);<o:p></o:p></P>
<P class=3DCprg>j =3D i <=3D 20 ? 7 < 3 ? "no"<SPAN=20
style=3D"mso-spacerun: yes"> </SPAN>: "bye" : "yes" =
;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(j);<o:p></o:p></P>
<P class=3DCprg>j =3D i <=3D 20 ? 7 > 3 ? "no"<SPAN=20
style=3D"mso-spacerun: yes"> </SPAN>: "bye" : "yes" =
;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(j);<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"><SPAN=20
style=3D"mso-spacerun: yes"> </SPAN><o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>yes<o:p></o:p></P>
<P class=3DCoutput>yes<o:p></o:p></P>
<P class=3DCoutput>bye<o:p></o:p></P>
<P class=3DCoutput>no<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 ?: operator is =
right=20
associative, which means that it gets evaluated from right to left. In =
the first=20
case, the compiler only sees the condition i >=3D 20. As it is false =
everything=20
in between the ? : is ignored and the string j contains yes. In the =
second case,=20
the same rule applies and the compiler misses the fact that we have =
changed=20
something from the ? to colon. In the third case, the condition is true, =
the=20
compiler proceeds to the ? onwards and here sees another conditional =
operator.=20
As it evaluates to false, the result is bye and in the last case it =
evaluates to=20
true and thus the result is no.<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">The type of the =
conditional=20
operator depends on the type of its two operands. In the above case, the =
type is=20
string as both the operands are strings.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -