zoukankan      html  css  js  c++  java
  • (原创)c#学习笔记06--函数02--变量的作用域01--其他结构中变量的作用域

    6.2  变量的作用域

      在上一节中,读者可能想知道为什么需要利用函数交换数据。原因是C#中的变量仅能从代码的本地作用域访问。给定的变量有一个作用域,访问该变量要通过这个作用域来实现。

      在上一节中,读者可能想知道为什么需要利用函数交换数据。原因是C#中的变量仅能从代码的本地作用域访问。给定的变量有一个作用域,访问该变量要通过这个作用域来实现。代码如下:

    class Program 
    { 
        static void Write() 
        { 
            Console.WriteLine("myString = {0}", myString); 
        } 
        static void Main(string[] args) 
        { 
            string myString = "String defined in Main()"; 
            Write(); 
            Console.ReadKey(); 
        } 
    }

      编译代码,注意显示在任务列表中的错误和警告:

    当前上下文中不存在名称“myString”【The name   'myString'   does not exist in the current context】
    变量“myString”已赋值,但其值从未使用过【The variable 'myString' is assigned but its value is never used】

      什么地万出错了?不能在Write()函数中访问在应用程序主体(Main()函数)中定义的变量myString。

      原因是变量是有作用域的,在这个作用域中,变量才是有效的。这个作用域包括定义变量的代码块和直接嵌套在其中的代码块。函数中的代码块与调用它们的代码块是不同的。在Write()中,没有定义myString,在Main()中定义的myString则超出了作用域——它只能在Main()中使用。

      实际上,在Write()中可以有一个完全独立的变量myString,修古代码,如下所示:

    class Program 
    { 
        static void Write()
        { 
            string myString = "String defined in Write()"; 
            Console.WriteLine("Now in Write()"); 
            Console.WriteLine("myString = {0}", myString); 
        } 
        static void Main(string[] args) 
        { 
            string myString = "String defined in Main()"; 
            Write(); 
            Console.WriteLine("
    Now in Main()"); 
            Console.WriteLine("myString = {0}", myString); 
            Console.ReadKey(); 
        } 
    }

      运行后可以看到结果。

      这段代码执行的操作如下:
        Main()定义和初始化字符串变量myString。
        Main()把控制权传送给Wri。
        Write()定义和初始化字符串变量myString,它与Main()中定义的myString变量完全不同。
        Write()把一个字符串输出到控制台上,该字符串包含在Write()中定义的myString的值。
        Write()把控制仅传送回Main()。
        Main()把一个字符串输出到控制台上,该字符串包含在Main()中定义的myString的值。

      其作用域以这种方式覆盖一个函数的变量称为局部变量。还有一种全局变量,其作用域可覆盖多个函数。修改代码,如下所示:

    class Program 
    { 
        static string myString; 
        static void Write() 
        { 
            string myString = "String defined in Write()"; 
            Console.WriteLine("Now in Write()"); 
            Console.WriteLine("Local myString = {0}", myString); 
            Console.WriteLine("Global myString = {0}", Program.myString); 
    } 
    
        static void Main(string[] args) 
        { 
            string myString = "String defined in Main()"; 
            Program.myString = "Global string"; 
            Write(); 
            Console.WriteLine("
    Now in Main()"); 
            Console.WriteLine("Local myString = {0}", myString); 
            Console.WriteLine("Global myString = {0}", Program.myString); 
            Console.ReadKey(); 
        } 
    } 

      这里添加了另一个变量myString,这次进一步加深了代码中的名称层次。这个变量定义如下:

    static string myString;

      注意,这里也需要static关键字。在这种类型的控制台应用程序中,必须使用static或const关键字,来定义这种形式的全局变量。如果要修改全局变量的值,就需要使用static,因为const禁止修改变量的值。

      为了区分这个变量和Main()与Write()中的同名局部变量,必须用一个完整限定的名称为变量名分类。这里把全局变量称为Program.myString。注意,在全局变量和局部变量同名时,这是必需的。如果没有局部myString变量,就可以使用myString表示全局变量,而不需要使用Program.myString。如果局部变量和全局变量同名,全局变量就会被屏蔽。

      是否使用全局变量取决于函数的位置。使用全局变量的问题在于,它们通常不适合于“常规用途”的函数——这些函数能处理我们所提供的任意数据,而不仅限于处理特定全局变量中的数据。

    6.2.1  其他结构中变量的作用域

      变量的作用域包含定义它们的代码块和直接嵌套在其中的代码块。这也可以应用到其他代码块上,例如分支和循环结构的代码块。考虑下面的代码:

    int i; 
    for (i = 0; i < 10; i++) 
    { 
        string text = "Line " + Convert.ToString(i); 
        Console.WriteLine("{0}", text); 
    } 
    Console.WriteLine("Last text output in loop: {0}", text); 

      字符串变量text 是for 循环的局部变量,这段代码不能编译,因为在该循环外部调用的Console.WriteLine()试图使用该变量text,这超出了循环的作用域。修改代码,如下所示:

    int i; 
    string text; 
    for (i = 0; i < 10; i++) 
    { 
        text = "Line " + Convert.ToString(i); 
        Console.WriteLine("{0}", text); 
    } 
    Console.WriteLine("Last text output in loop: {0}", text);

      这段代码也会失败,原因是必须在使用变量前对其进行声明和初始化,而text 是在for循环中初始化的。赋给text的值在循环块退出时就丢失了。但是还可以进行如下修改:

    int i; 
    string text = ""; 
    for (i = 0; i < 10; i++) 
    { 
        text = "Line " + Convert.ToString(i); 
        Console.WriteLine("{0}", text); 
    } 
    Console.WriteLine("Last text output in loop: {0}", text); 

      只声明一个简单变量类型,并不会引起其他的变化。只有在给变量赋值后,这个值才占用一块内存空间。如果这种占据内存空间的行为在循环中发生,该值实际上定义为一个局部值,在循环的外部会超出了其作用域。

      即使变量本身没有局部化到循环上,循环所包含的值也局部化到该循环上。但是,在循环外部赋值可以确保该值是主体代码的局部值,在循环内部它仍处于其作用域中。这意味着变量在退出主体代码块之前是没有超出作用域的,所以可以在循环外部访问它的值。

      最后一个要注意的问题是,应采用“最佳实践方式”。一般情况下,最好在声明和初始化所有变量后,再在代码块中使用它们。一个例外是把循环变量声明为循环块的一部分,例如:

    for (int i = 0; i < 10; i++) 
    { 
        ... 
    }
  • 相关阅读:
    aiohttp简介及快速使用
    Git的学习与使用
    基于scrapy-redis的分布式爬虫
    异步编程之asyncio简单介绍
    Scrapy框架中的CrawlSpider
    scrapy中selenium的应用
    ua池和代理池
    Scrapy持久化存储
    Scrapy的日志等级和请求传参
    virtualenv搭建Python虚拟环境
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/4912236.html
Copyright © 2011-2022 走看看