📄 chapter 6.mht
字号:
compiler. In the above case, we presumed the compiler would face a =
dilemma. It=20
could either convert the byte to a decimal, or convert a yyy object to a =
string=20
and then call the plus operator. It prefers the first option as it means =
fewer=20
steps to be carried out. Remove the plus operator totally and the second =
option=20
will get executed. The string operator of the class yyy is called =
which<SPAN=20
style=3D"mso-spacerun: yes"> </SPAN>returns a string This is then=20
concatenated with 10 to display hi10.<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>public 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>yyy a =3D new yyy();<o:p></o:p></P>
<P class=3DCprg>sbyte i =3D 10;<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(a+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<SPAN style=3D"mso-spacerun: yes"> =20
</SPAN><o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static string operator + (yyy b,decimal =
x)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return "decimal " + x;<o:p></o:p></P>
<P class=3DCprg>} <o:p></o:p></P>
<P class=3DCprg>public static implicit operator string ( yyy =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return "hi";<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>public static implicit operator byte ( yyy =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return 21;<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>decimal 10<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 compiler has a =
one-track=20
mind. It always prefers an implicit numeric conversion. It could have =
converted=20
the yyy object to a byte and then called the predefined plus to add two =
numbers.=20
It did not do it then for a string, it will not do it now either for two =
numbers. It has its own preferences on doing things its way. If we =
remove the=20
operator plus code from the class, we get the following error.<SPAN=20
style=3D"mso-spacerun: yes"> </SPAN><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=3DCoutput><U>Compiler Error</U><o:p></o:p></P>
<P class=3DCoutput>a.cs(7,26): error CS0034: Operator '+' is ambiguous =
on operands=20
of type 'yyy' and 'byte'<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">Here the compiler has =
no=20
preferences over calling the string or the byte conversion operators. =
Hence, it=20
flags an error whenever it cannot make up its mind or is in two minds. =
The=20
documentation came up with other rules for the other data types. We have =
copied=20
them and would advise you to remember them on a rainy day.=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">Byte to short, =
ushort, int, uint,=20
long, ulong, float, double, or decimal. Short to int, long, float, =
double, or=20
decimal. Ushort to int, uint, long, ulong, float, double, or decimal. =
Int to=20
long, float, double, or decimal. Uint to long, ulong, float, double, or =
decimal.=20
Long to float, double, or decimal. Ulong to float, double, or decimal. =
Char to=20
ushort, int, uint, long, ulong, float, double, or decimal and finally =
Float to=20
double. <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">We have no choice but =
to have a=20
piece of paper with the above rules written down as a ready reckoner. We =
feel=20
very guilty when we copy-paste from the documentation and avoid doing it =
like=20
the plague. However, we have no choice as rules are rules are=20
rules!!.<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">Finally, a char =
stores unicode=20
characters which are finally numbers. Working with chars is a one-way =
street.=20
You are allowed to convert a char to another data type but not vice =
versa. For=20
instance, a byte cannot be converted to a char.<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">An implicit =
enumeration=20
conversion lets the number zero be converted to any enum type. This was=20
expected, as an enum is nothing but a glorified number with a=20
name.<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">Implicit=20
Reference conversions<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=3DCbase><SPAN style=3D"COLOR: windowtext">The above conversions =
are what we=20
have been talking about throughout this book. The only difference is =
that we are=20
pegging a label or a name to what we already know. All reference objects =
can be=20
scaled down to an object without a murmur. A derived class can be scaled =
down to=20
a base class or a base interface. Ditto for interfaces derived from each =
other.=20
Any array type is scaled to System.Array and delegate to =
System.Deleagte. In=20
turn, an array or a delegate can also become an interface =
System.IClonable. The=20
null type can be used to initialize any reference object. =
<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">Arrays at times pose =
a small=20
problem. We can equate arrays only if they are of the same dimension and =
they=20
store reference types. Then they become simple objects and a conversion =
must=20
exist to convert one to the other. These do not require any compile time =
checks=20
and do not change the value of the object, they may change the data type =
only.<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">Implicit constant =
conversions=20
only deal with constants. They are very simple in nature. An int can be=20
converted to a sbyte, byte, short, ushort, uint, or ulong provided the =
range of=20
the destination is not exceeded. In the same way , a ulong can be =
converted to a=20
long. How boring! Makes us feel sleepy writing all this original =
travail. How=20
many times did you yawn? We, a hundred thousand =
times!<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">Explicit=20
Conversions<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=3DCbase><SPAN style=3D"COLOR: windowtext">Explicit conversions =
are made up=20
of all implicit conversions, explicit numeric conversions, explicit =
enumeration=20
conversions, explicit reference conversions, explicit interface =
conversions,=20
unboxing conversions and finally user-defined explicit conversions. =
Remember,=20
for the last time, an explicit conversion only exists in a cast =
expression. It=20
is like beauty, it can only lie in the eyes of the beholder.=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">An explicit =
conversion has a=20
large number of useful properties. It may or may not succeed. There is =
no way to=20
prove that explicit conversions will always succeed and that is why they =
are=20
placed in the explicit category. We may lose some information on our =
path to=20
conversion. Perfectly acceptable. They also have vision and can convert =
from a=20
large range of domain types. We can have as many redundant casts as we =
like in a=20
single expression. <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>public class zzz {<o:p></o:p></P>
<P class=3DCprg>public static void Main() {<o:p></o:p></P>
<P class=3DCprg>yyy a =3D new yyy();<o:p></o:p></P>
<P class=3DCprg>yyy b =3D (xxx)(aaa) a;<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<SPAN style=3D"mso-spacerun: yes"> =20
</SPAN><o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator aaa( yyy =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("op aaa");<o:p></o:p></P>
<P class=3DCprg>return new aaa();<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 aaa<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator xxx( aaa =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("op xxx");<o:p></o:p></P>
<P class=3DCprg>return new xxx();<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("op yyy");<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=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>op aaa<o:p></o:p></P>
<P class=3DCoutput>op xxx<o:p></o:p></P>
<P class=3DCoutput>op 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">In the above case, we =
have come a=20
full circle. We are first converting a yyy object into an aaa object =
then to an=20
xxx object and finally, once again to a yyy object. We can have as many =
casts as=20
we want on a single line and the compiler will do our bidding for us. It =
does=20
not check the veracity of our casting nor does it realize that we are =
coming=20
back to square one. Thus, multiple redundant casts are allowed=20
always.<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">Explicit numeric=20
conversions<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>public 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>char i =3D 'A';<o:p></o:p></P>
<P class=3DCprg>short b =3D 65;<o:p></o:p></P>
<P class=3DCprg>i =3D 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,5): error CS0029: Cannot implicitly convert =
type 'short'=20
to 'char'<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 told you earlier =
that a char=20
cannot be converted to any other data type but the reverse was possible. =
Now we=20
want the above conversion to work, by hook or =
crook.<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 + -