100162740.htm

来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 196 行 · 第 1/3 页

HTM
196
字号
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">方法的局部变量必须在代码中显式初始化,之后才能在语句中使用它们的值。此时,初始化不是在声明该变量时进行的,但编译器会通过方法检查所有可能的路径,如果检测到局部变量在初始化之前就使用了它的值,就会产生错误。</span></p>
<p class="MsoNormal"><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">的方法与</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">的方法相反,在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">中,编译器让程序员确保变量在使用之前进行了初始化,在</span><span lang="EN-US">VB</span><span style="FONT-FAMILY: 宋体">中,所有的变量都会自动把其值设置为</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">例如,在</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">中不能使用下面的语句:</span></p>
<p class="2" style="MARGIN: 6.5pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">public static int Main()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; int d;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; Console.WriteLine(d);&nbsp;&nbsp; // Can't do this! Need to initialize d before use</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; return 0;</span></p>
<p class="2" style="MARGIN: 0cm 0cm 6.5pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">注意在这段代码中,演示了如何定义</span><span lang="EN-US">Main()</span><span style="FONT-FAMILY: 宋体">,使之返回一个</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体">类型的数据,而不是</span><span lang="EN-US">void</span><span style="FONT-FAMILY: 宋体">的数据。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在编译这些代码时,会得到下面的错误消息:</span></p>
<p class="a6" style="MARGIN: 4.9pt 0cm 4.9pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Use of unassigned local variable 'd'</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">同样的规则也适用于引用类型。考虑下面的语句:</span></p>
<p class="2" style="MARGIN: 6.5pt 0cm 6.5pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">Something objSomething;</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 15pt"><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">中,上面的代码会在堆栈中创建</span><span lang="EN-US">Something</span><span style="FONT-FAMILY: 宋体">类的一个实例。在</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">中,这行代码仅会为</span><span lang="EN-US">Something</span><span style="FONT-FAMILY: 宋体">对象创建一个引用,但这个引用还没有指向任何对象。对该变量调用方法或属性会导致错误。</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 15pt"><span><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">C#</span></span><span style="FONT-FAMILY: 宋体">中实例化一个引用对象需要使用</span><span lang="EN-US">new</span><span style="FONT-FAMILY: 宋体">关键字。如上所述,创建一个引用,使用</span><span lang="EN-US">new</span><span style="FONT-FAMILY: 宋体">关键字把该引用指向存储在堆上的一个对象:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span><span lang="EN-US">objSomething = new</span></span><span lang="EN-US"> Something();&nbsp;&nbsp; // This creates a Something on the heap</span><span></span></p>
<h3 style="MARGIN: 8.15pt 0cm"><span><span lang="EN-US">2.3.2 &nbsp;</span></span><span style="FONT-FAMILY: 黑体">变量的</span><span style="FONT-FAMILY: 黑体">作用域</span></h3>
<p class="MsoNormal"><span><span style="FONT-FAMILY: 宋体">变量的作用域是可以访问该变量的代码区域。一般情况下,确定作用域有以下规则:</span></span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">只要字段所属的类在某个作用域内,其字段</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">也称为成员变量</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">也在该作用域内</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US">Java</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"> VB</span><span style="FONT-FAMILY: 宋体">中也是这样</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; TEXT-INDENT: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">局部变量存在于表示声明该变量的块语句或方法结束的封闭花括号之前的作用域内。</span></p>
<p class="1" style="MARGIN-LEFT: 37.85pt; TEXT-INDENT: -16.4pt"><span lang="EN-US" style="LETTER-SPACING: 0.1pt">●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">在</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US">while</span><span style="FONT-FAMILY: 宋体">或类似语句中声明的局部变量存在于该循环体内</span><span lang="EN-US">(C++</span><span style="FONT-FAMILY: 宋体">程序员注意,这与</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体">的</span><span lang="EN-US">ANSI</span><span style="FONT-FAMILY: 宋体">标准相同。</span><span lang="EN-US">Microsoft C++</span><span style="FONT-FAMILY: 宋体">编译器的早期版本不遵守该标准,但在循环停止后这种变量仍存在</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。</span></p>
<h4 style="TEXT-INDENT: 21.45pt"><span lang="EN-US">1. </span><span style="FONT-FAMILY: 黑体">局部变量的作用域冲突</span></h4>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">大型程序在不同部分为不同的变量使用相同的变量名是很常见的。只要变量的作用域是程序的不同部分,就不会有问题,也不会产生模糊性。但要注意,同名的局部变量不能在同一作用域内声明两次,所以不能使用下面的代码:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">int x = 20;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">// some more code</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">int x = 30;</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">考虑下面的代码示例:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">using System;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">namespace Wrox.ProCSharp.Basics</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; public class ScopeTest</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static int Main()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 10; i++)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(i);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; // i goes out of scope here</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // We can declare a variable named i again, because</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // there's no other variable with that name in scope</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 9; i &gt;= 0; i--)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(i);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; // i goes out of scope here</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp; &nbsp;}</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这段代码使用一个</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体">循环打印出从</span><span lang="EN-US">0~9</span><span style="FONT-FAMILY: 宋体">的数字,再打印从</span><span lang="EN-US">9~0</span><span style="FONT-FAMILY: 宋体">的数字。重要的是在同一个方法中,代码中的变量</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体">声明了两次。可以这么做的原因是在两次声明中,</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体">都是在循环内部声明的,所以变量</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体">对于循环来说是局部变量。</span></p>
<p class="MsoNormal"><span lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">下面看看另一个例子:</span></p>
<p class="2" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static int Main()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j = 20;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 10; i++)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j = 30; &nbsp;&nbsp;// Can't do this - j is still in scope</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(j + i);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; TEXT-INDENT: 18.45pt; LINE-HEIGHT: 13pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</span></p>
<p class="2" style="MARGIN: 0cm 0cm 8.15pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">如果试图编译它,就会产生如下错误:</span></p>
<p class="a6" style="MARGIN: 8.15pt 0cm 0pt 21.45pt; TEXT-INDENT: 18.45pt"><span lang="EN-US">ScopeTest.cs(12,14): error CS0136: A local variable named 'j' cannot be declared in this scope because it <span style="LETTER-SPACING: -0.1pt">would give a different meaning to 'j', which is already used in a 'parent or current' scope to denote something else</span></span></p>

⌨️ 快捷键说明

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