⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter 6.mht

📁 C# Nuts and Bolt是学习C#的极好教程
💻 MHT
📖 第 1 页 / 共 5 页
字号:
operator is not=20
supposed to throw an exception. Remember an exception is thrown when =
something=20
goes wrong. We are not supposed to lose information in a user-defined=20
conversion. By convention, an implicit operator never throws an =
exception,=20
whereas an explicit one is allowed to. You are permitted to float a =
convention=20
at your own peril.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<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>}<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>class yyy<SPAN style=3D"mso-spacerun: yes">&nbsp;=20
</SPAN><o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator xxx (yyy =
b)<o:p></o:p></P>
<P class=3DCprg>{<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>public static xxx op_Implicit(yyy b)<o:p></o:p></P>
<P class=3DCprg>{<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>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Compiler Error</U><o:p></o:p></P>
<P class=3DCoutput>a.cs(13,19): error CS0111: Class 'yyy' already =
defines a member=20
called 'op_Implicit' with the same parameter types<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">By throwing the above =
exception,=20
we now know that our conversion operator is renamed to a function called =

op_Implicit with one parameter, a yyy object in the above case. What if =
we have=20
two such conversion operators?<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<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>aaa b =3D new aaa();<o:p></o:p></P>
<P class=3DCprg>xxx c =3D new xxx();<o:p></o:p></P>
<P class=3DCprg>try<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>b =3D a;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>catch ( System.Exception e) <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(e);<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>try<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>c =3D a;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>catch ( System.Exception e) <o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(e);<o:p></o:p></P>
<P class=3DCprg>}<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">&nbsp;=20
</SPAN><o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator xxx (yyy =
b)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>throw new System.Exception();<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>public static implicit operator aaa(yyy =
c)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>throw new System.Exception();<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 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 aaa<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]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>System.Exception: An exception of type =
System.Exception was=20
thrown.<o:p></o:p></P>
<P class=3DCoutput><SPAN style=3D"mso-spacerun: yes">&nbsp;&nbsp; =
</SPAN>at=20
yyy.op_Implicit(yyy c)<o:p></o:p></P>
<P class=3DCoutput><SPAN style=3D"mso-spacerun: yes">&nbsp;&nbsp; =
</SPAN>at=20
zzz.Main()<o:p></o:p></P>
<P class=3DCoutput>System.Exception: An exception of type =
System.Exception was=20
thrown.<o:p></o:p></P>
<P class=3DCoutput><SPAN style=3D"mso-spacerun: yes">&nbsp;&nbsp; =
</SPAN>at=20
yyy.op_Implicit(yyy b)<o:p></o:p></P>
<P class=3DCoutput><SPAN style=3D"mso-spacerun: yes">&nbsp;&nbsp; =
</SPAN>at=20
zzz.Main()<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">Here is what =
surprises us. We=20
always thought that two functions could not ever have the same name. =
Here the=20
compiler has converted the implicit functions to have the same name and =
if we=20
had not changed the name of the object in the parameter list from b to =
c, they=20
would have been identical. In the earlier example, where we had a =
function=20
called op_ Implicit, the compiler, gave us an error, but in the above =
example,=20
the compiler actually scales down to two functions with the same name.=20
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">How does it =
internally separate=20
them, we have no idea at all. Life is a drag. One set of rules for the =
compiler,=20
another set for us. The compiler can break rules with impunity, we =
cannot.=20
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">There are seven types =
of implicit=20
conversions, which are identity, implicit numeric, implicit enumeration, =

implicit reference, boxing, implicit constant expression and finally=20
user-defined implicit conversions.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">We are allowed to =
equate any type=20
to our user-defined type. This type of conversion is called an identity=20
conversion where it lets an entity of a particular type to be converted =
to the=20
type we want.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<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">&nbsp;=20
</SPAN><o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static string operator + (yyy b,int =
x)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return "int " + x;<o:p></o:p></P>
<P class=3DCprg>} <o:p></o:p></P>
<P class=3DCprg>public static string operator + (yyy b,short =
x)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return "short " + x;<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>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>short 10<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">An implicit numeric =
conversion=20
converts an sbyte to short, int, long, float, double, or decimal. The =
above line=20
is courtesy Mr Documentation. It simply means that whenever the compiler =
sees a=20
byte, it will try and find a matching function or operator that accepts =
a byte=20
as a parameter. In this case, there is no operator + that accepts a byte =
as a=20
parameter. So, the compiler now looks for another function that accepts =
a short=20
as a parameter. If it finds one, it promotes the byte to a short, rolls =
up its=20
sleeves and calls the function. Thus, we get short 10 displayed as the =
result.=20
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">C# does all of this =
without=20
taking our permission. Thus it is called an implicit numeric conversion =
because=20
it happens silently in the background without our knowledge. When we =
remove the=20
code of the operator + that accepts a short, we get the following=20
answer.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>int 10<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">The answer is very =
intuitive. The=20
compiler starts the whole process explained above once again. It first =
tries to=20
find a function that accepts a short. No luck. The compiler does not =
give up and=20
now tries to find one that accepts an int. Bingo, it finds one so it =
executes=20
the function. <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">If we now remove the =
plus=20
operator with the int, then only the one with decimal stays. As per the =
above=20
rules, a match will be found and the function will be called.=20
<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">The order of =
conversion is as=20
decided by the compiler. We cannot change the above order, all that we =
can do is=20
gracefully accept it and carry on with life. If you notice, this order =
is from=20
small to large in terms of memory allocation by the compiler. The order =
makes a=20
lot of sense now.<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<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">&nbsp;=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>}<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext"><![if =
!supportEmptyParas]><![endif]>&nbsp;<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]>&nbsp;<o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">Strange are the ways =
of a=20

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -