📄 chapter 9.mht
字号:
<P class=3DCbase><B><SPAN=20
style=3D"FONT-SIZE: 14pt; COLOR: windowtext; FONT-FAMILY: Tahoma">Name=20
Hiding<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">Name hiding occurs =
when we=20
inherit from a class or struct and erroneously or otherwise, we =
introduce a=20
similar name as that in the base class. A constant, field, property, =
event, or=20
type hides the base class members with the same =
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=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>System.Console.WriteLine(a.i);<o:p></o:p></P>
<P class=3DCprg>a.i =3D 100;<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 : xxx<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public int i =3D 3;<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 const int i =3D 10;<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(13,12): warning CS0108: The keyword new is =
required on=20
'yyy.i' because it hides inherited member 'xxx.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=3DCoutput><U>Output</U><o:p></o:p></P>
<P class=3DCoutput>3<o:p></o:p></P>
<P class=3DCoutput>100<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"><![if =
!supportEmptyParas]><![endif]> <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">A million years ago, =
someone=20
somewhere in the world created a class called xxx. That gentleman, then, =
added=20
one const member called i. For some reason, we decided to derive from =
class xxx.=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">We are allowed to =
create our own=20
variable i notwithstanding the fact that it was declared to be a const =
in class=20
xxx. Other than a warning issued by the compiler, we are allowed =
complete=20
freedom in using whatever names we like in our derived classes, thus =
oblivious=20
to what the base class has given.<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>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 : xxx<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public void i()<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("hi");<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 const int i =3D 10;<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>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">As stated earlier, we =
have total=20
freedom in doing what we like within the derived class. In the above =
example,=20
the function i has nothing to do with the const i in class xxx. The =
compiler=20
does send you a feeble protest in the form of a simple warning but that =
can be=20
ignored with no loss of life or limb. The same rules apply to indexers =
also. As=20
repeated earlier, operators can never hide each other=20
ever.<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">Concealing an =
inherited member=20
does not issue any error as it would then prevent evolving any base =
classes=20
independently. Lets us explain why a warning and not an error.=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">Let us assume that we =
are=20
deriving from a base class that has a function called pqr. We now =
decided to=20
create an abc function in the derived class. After a while, the next =
version of=20
the base class, for some reason, introduces a new function called abc. =
At that=20
moment, all derived classes from the base class should not break or give =
an=20
error. In the scheme of things followed by C#, they are different =
functions and=20
making changes to a base class does not invalidate existing derived =
classes at=20
all.<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">Functions<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">There are five places =
in the C#=20
language where we can place executable code. These places are =
constructors,=20
methods, properties, indexers and user-defined operators. Anywhere else, =
and you=20
permission from the silicon god that is not very forthcoming. Function =
members=20
are not members of a namespace and thus we can only place the above in a =
type.=20
You cannot have global functions that are not associated with a type. We =
cannot=20
use ref and out parameters for indexers, properties or operators. These =
have to=20
be value parameters 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=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>zzz a =3D new zzz();<o:p></o:p></P>
<P class=3DCprg>int i =3D 0;<o:p></o:p></P>
<P class=3DCprg>a.abc(i++,i++,i++);<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>public void abc( int x, int y, int z)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(x + " " + y + " " + =
z);<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>0 1 2<o:p></o:p></P>
<P class=3DCoutput>3<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 parameters to a =
function are=20
read in the order they are written, from left to right. Thus even though =
we are=20
using a postfix notation, i++, the compiler uses the current value of i =
to=20
initialize parameter x in function abc, and then increase i by one. =
Thus, i now=20
has a value of one, that is what the parameter y is initialized to and =
then it=20
is increased by one. This z becomes two and at the end of the function=20
invocation variable i has a value of three.<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">Object =
Elements<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>byte [] b =3D new byte[2];<o:p></o:p></P>
<P class=3DCprg>b[1] =3D 10;<o:p></o:p></P>
<P class=3DCprg>yyy a =3D new yyy();<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(b[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<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator int(yyy =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>return 1;<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>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">If we remove the =
overloaded=20
operator int, we get the following error.<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(8,28): error CS0029: Cannot implicitly convert =
type 'yyy'=20
to 'int'<o:p></o:p></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">The variable we use =
in the []=20
brackets is called the element access and must be one of the following =
data=20
types namely int, uint, long, ulong or any type that can be implicitly =
converted=20
to the above type. Thus, without the operator int which was responsible =
for=20
converting the yyy to an int, we got the above error. On returning 1 in =
the=20
operator, the array variable becomes b[1].<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>byte [] b =3D new byte[2];<o:p></o:p></P>
<P class=3DCprg>b[1] =3D 10;<o:p></o:p></P>
<P class=3DCprg>yyy a =3D new yyy();<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine(b[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<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>public static implicit operator uint(yyy =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("uint");<o:p></o:p></P>
<P class=3DCprg>return 1;<o:p></o:p></P>
<P class=3DCprg>}<o:p></o:p></P>
<P class=3DCprg>public static implicit operator long(yyy =
a)<o:p></o:p></P>
<P class=3DCprg>{<o:p></o:p></P>
<P class=3DCprg>System.Console.WriteLine("long");<o:p></o:p></P>
<P class=3DCprg>return 1;<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>uint<o:p></o:p></P>
<P class=3DCoutput>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">Rules, rules =
everywhere, but not=20
a drop to drink. The element access of an array as stated earlier must =
either be=20
an int, uint, long or a ulong. The above order must be followed. The =
compiler=20
checks for the operators in the above order and on finding the very =
first match,=20
it uses that operator. It stops short in its tracks and does not =
complain that=20
it could use both the above operators. <o:p></o:p></SPAN></P>
<P class=3DCbase><SPAN style=3D"COLOR: windowtext">It is one of the few =
cases where=20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -