当前位置: 代码迷 >> C# >> 5.步骤
  详细解决方案

5.步骤

热度:79   发布时间:2016-05-05 03:03:37.0
5.方法

5.1 方法的结构, 方法的大多数内容不仅针对类同样适用于struct中的方法

        1.方法是一块具有名称的代码。可以使用方法的名称从别的地方执行代码,也可以把数据传入方法并接受数据输出。
        2.方法是类的函数成员。方法有两个主要部分,方法头和方法体。
                1.方法头指定方法的特征,包括
                    方法是否返回数据,如果返回,返回什么类型  (返回值类型)
                    方法的名称    (方法的名称)
                    哪种类型的数据可以被传送并源自方法,以及应如何处理该数据。(方法的参数)
                2.方法体包含可执行代码的语句序列。执行从方法体的第一条语句开始,一直到这个方法结束
                        方法体是一个块,是大括号阔气的语句序列,块可以包含以下几个项目:        
                                1.本地变量    即 在块中声明的变量
                                2.控制流结构        如 if  else 等
                                3.方法调用            在块内部调用方法
                                4.内嵌的块            如:while循环语句块
 
5.2 本地变量
        1.本地变量的存在性仅限于创建它的块及其内嵌的块
              它从声明它的那一点开始存在
               它在它所在的块完成执行时结束存在
        2.可以在方法体内任意位置声明本地变量,但必须在使用它们前声明。
                                对比实例字段和本地变量
 实例字段本地变量
生存期从实例被创建时开始,直到实例不在被访问时结束从它在块中被声明的那点开始,在其所在的块完成执行时结束
隐式初始化初始化成该类型的默认值没有隐式初始化,如果变量在使用之前没有被赋值,编译器就会产生一条错误信息
存储区域类的所有字段都存储在堆里,无论他们是值类型还是引用类型值类型:存储在栈里
引用类型:引用存储在栈里,数据存储在堆里
 
5.2.1 类型推断和var关键字(var关键字是本地变量的万能侦测类型)
   使用var关键字有一些重要的条件:
        1.只能用于本地变量,不能用于字段
        2.只能在变量声明中包含初始化时使用
        3.一点编译器推断出变量的类型,他就是固定且不能更改的
 
5.3 本地常量
       1. 本地常量很像本地变量,只是一旦它被初始化,它的值就不能被改变。如同本地变量,本地常量必须声明在块的内部
        2.常量的两个最重要的特征如下:
                1.常量在声明中必须初始化
                2.常量在声明后不能改变。
       3.常量的核心声明如下所示。语法与字段或变量的声明相同,除了下面内容
                1.在类型之前增加关键字 const
                2.必须有初始化语句。初始化值必须在编译期决定,通常是一个预定义简单类型或由其组成的表达式。它还可以是null的引用,但他不能是摸个对象的引用,因为对象的引用时在运行时决定的。
        说明:关键字const 不是一个修饰符, 而是核心声明的一部分。它必须直接放在类型的前面。如:const Type Identifier = value; value初始化值是必须的。
 
控制流:
    术语控制流指的是程序从头到尾的执行流程。默认情况下,程序执行持续的从一条语句到下一条语句,控制语句允许你改变执行的顺序。
    1.选择语句  这些语句可以选择哪条语句或语句块执行
                if   有条件的执行一条语句
                if ...  else  有条件的执行一条或另一个语句
                switch    有条件的执行一组语句中的一条
   2.迭代语句    这些语句可以在一个语句块上循环或迭代
            for  循环 ——在顶部测试
            while 循环——在顶部测试
            do循环——在底部测试
            foreach——为一组中每个成员执行一次
   3.跳转语句   这些语句可以让你从代码块或方法体内部的一个地方跳到另一个地方。
    break   跳出当前循环
    continue  到当前循环的底部
    goto 到一个命名的语句
    return 返回到发起调用的方法
5.6 方法参数:作用:方法的返回值,传递方法参数
       5.6.1 实参:
            当代码调用一个方法时,形参的值必须在方法的代码开始执行之前被初始化
            1.用于初始化形参的表达式或变量称作实参(actual parameter,有时也简称argument)
            2.实参位于方法调用的参数列表中
            3.每个实参必须与对应形参的类型相匹配,或者编译器必须能把实参隐式转换为哪个类型
 
5.7值参数和引用参数:
  准备知识:
    形参:是当我们声明方法时,为方法声明的方法参数
    实参:当我们调用方法时,传递的参数
    值类型放在栈中,而引用类型放在堆中而它的引用放在栈中
 当我们向调用的方法传递参数时,如果参数的类型是值类型,则传递的是值类型参数的副本,所以当在调用的方法中改变了传递进来参数的值后,当调用的方法运行完之后形参声明周期结束,但是实参的值并为改变,因为 调用方法时传递的是值类型的副本,当参数类型是引用类型时,传递的是那个实参复制后的变量,因为是引用类型所以当在调用的方法中将方法引用类型参数的值改变后,实参的值也会变化,原因是它们都指向堆中的同一实体,所以可以通过 ref关键字 将实参传递进到调用的方法中,而不再是复制后的而是其本身。
值参数和引用参数:
这种将参数复制一下传递给调用的方法是值参数也是系统默认的形式,注:这种形式是值参数不要和值类型 相互混淆,而使用ref关键字将本身传递给调用的方法的是引用参数
值参数需要注意的地方:
    在把变量用作实参之前,变量必须被赋值(除非是输出参数),对于引用类型,变量可以被设置为实际引用或null,在值参数形式下传递参数时也可以传递具体的值或表达式 如:add(1,2);
引用参数要注意的地方:
    使用引用参数时,必须在方法的声明和调用中都是用ref关键字
    实参必须是变量,在用作实参前必须被赋值,如果是引用类型变量,可以赋值为一个引用或null值
 
5.9 输出参数:
  输出参数用于从方法体内把数据传出到调用代码,它们非常类似引用参数,如同引用参数,输出参数有以下要求。
    1.必须在声明和调用中都是用修饰符,输出参数的修饰符是out而不是ref。
    2.和引用参数相似,实参必须是变量,而不能是其他类型的表达式。这也是有道理的,因为方法需要内存位置保存返回值
 与引用参数不同,输出参数有以下要求:
    1.在方法内部,输出参数在被读取之前必须被赋值。这意味着参数的初始值是无关的,而且没有必要再方法调用之前为实参赋值。
    2.在方法返回之前,方法内部的任何贯穿的可能路径都必须为所有输出参数进行一次赋值
  在方法内部要想读取输出参数的值,则必须先给给输出参数赋值,因为输出参数侧重于输出参数,所以传递进来的可能是空。
 
5.10 参数数组:
   1.格式:   一般参数类型都必须严格地一个实参对应一个形参。参数数组不一样,它允许零个或多个实参对应一个特殊的形参。参数数组的重点如下:
            1.在一个参数列表中只能有一个参数数组
            2.如果有,它必须是列表中的最后一个。
        声明参数数组必须做的事如下:
            1.在数据类型前使用params修饰符
            2.在数据类型后放置一组空的方括号
  1. 例如:voidListInts(paramsint[] inVals){....}
  2.方法调用:
        有两个方法提供实参,可以使用如下形式:
        1.一个逗号分隔的该数据类型元素的列表。所有元素必须是方法中指定的类型
  1. 如:ListInts(10,20,30);
        2.一个该数据类型元素的一维数组
  1. 如:int[] intArray ={1,2,3};
  2. ListInts( intArray ); //这种是引用参数
  请注意:在这些事例中,并不在调用时使用params修饰符。参数数组中修饰的使用并不适用于其他参数类型的模式
        1.其他参数类型要么使用修饰符,要么不使用修饰符。
                1.值参数的声明和调用都不带修饰符
                2.引用参数和输出参数在两个地方都需要修饰符。
        2.params修饰符的用法总结如下。
                1.在声明中需要修饰符
                2.在调用中不允许有修饰符
延伸式
    方法调用的第一种形式有时被称为延伸式,这种形式在调用中使用分离的实参
        例如,下面代码中的方法ListInts的声明可以匹配它下面所有的方法调用,虽然他们有不同数目的实参。
  1. voidListInts(paramsint[] inVals){...}//方法声明
  2. ListInts();//0实参
  3. ListInts(1,2,3);//3实参
  4. ListInts(4,5,6,7);//4实参
  5. ListInts(8,9,10,1112);//5实参
  6. //以上这些事值参数

    使用一个为参数数组分离实参的调用时,编译器做下面的事。
        1.接受实参列表,用它们在堆中创建并初始化一个数组
         2把数组的引用保存到栈中的形参里
        3.如果在对应的形参数组的位置没有实参,编译器会创建一个有0个元素的数组来使用
 
注意:在写参数数组方法实现的时候要首先判断是否为空和长度是否大于0
  1. publicvoidListInts(paramsint[] a){
  2. if(a !=null&& a.Length!=0)
  3. {
  4. for(int i =0; i < a.Length; i++)
  5. {
  6. a[i]= a[i]*10;
  7. Console.WriteLine(a[i]);
  8. }
  9. }
  10. }
 
关于参数数组,需要记住的重要一点是当数组在堆中被创建时,实参的值被复制到数组中。在这方面,它们向值参数。
    1.如果数组参数是值类型,那么值被赋值,实参不受方法内部的影响。
    2.如果数组参数时引用类型,那么引用被赋值,实参引用的对象可以收到方法内部的影响。
 
参数类型总结:
                                        参数类型语法使用总结
参数类型修饰符是否在声明时使用是否在调用时使用执 行
  系统把实参的值复制到形参
引用ref形参是实参的别名
输出out形参是实参的别名
数组params允许传递可变数目的实参到方法
 
5.12  方法重载
             1.一个类中可以有一个以上的方法拥有相同的名称,这叫做方法的重载(method overload)。使用相同名称的每个方法必须有一个和其他方法不相同的签名(signature)。
            2.方法的签名由下列信息组成,它们在方法声明的方法头中:
                    1.方法的名称
                    2.参数的数目
                    3.参数的数据类型和顺序
                    4.参数的修饰符
            3.注意:返回类型不是签名的一部分
 
5.13 命名参数,调用方法的时候可以改变形参的位置赋值
        1.从c#4.0开始,只要显示指定参数的名字,就可以以任意顺序在方法调用中列出实参。
                1.方法的声明不变
                2.在调用的时候,形参的名字后面跟着冒号和实际的参数值或表达式,如:
  1. //声明一个方法
  2. publicvoidAdd(int num1,int num2,int num3){...}
  3. //调用方法
  4. Add( num2:1, num3:2, num1:3);
5.14 可选参数
            1. c#4.0引入的另一个特性叫做可选参数。所谓的可选参数就是我们可以在调用方法的时候包含这个参数,也可以省略它。
            2.为表名某个参数是可选的,你需要在方法声明的时候为参数提供默认值。指定默认值的语法和初始化本地变量的语法一样。
    如:
  1. //声明可选参数的方法
  2. publicintAdd(int num1,int num2 =0)
  3. {
  4. ...
  5. }
  6. //调用可选参数的方法
  7. //第一种
  8. Add(1,2);
  9. //第二种
  10. Add(1); // 当不给可选的参数赋值时,则可选参数使用默认的值
         3.对于可选参数的声明,我们需要知道如下几个重要事项
            1.不是所有的参数类型都可以作为可选参数。
                 1.只要值类型的默认值在编译的时候可以确定,就可以使用值类型作为可选参数。
                 2.只要在默认值是null的时候,引用类型才可以用作可选参数来使用。
              
                                                            参数类型
    






 refoutparams
值类型
引用类型只允许为null的默认值
可选参数只能是值参数类型
 
      2.所有必填参数必须在可选参数声明之前声明。如果有params参数,必须在所有可选参数之后声明
        如:(int x , decimal y , .....     int op1 = 17 , double op2 = 36 , .....   params int[] intVals)
        当方法中的可选参数多的时候,我们不能随意省略可选参数的组合,因为在很多情况下这么做会导致使用哪些可选参数不明确,规则如下、  :
            1. 你必须从可选参数列表的最后开始省略,一直到列表开头。 也就是说,你可以省略最后一个可选参数,或是最后n个参数,但是不可以随意选择省略任意的可选参数,省略必须从最后开始。    
            2.如果需要随意省略可选参数列表中的可选参数,而不是从列表中的最后开始,那么必须使用可选参数的名字来消除赋值的歧义。也就是说,需要结合命名参数和可选参数可行
 
5.15 栈帧
 在调用方法的时候,内存从栈的顶部开始分配,保存和方法关联的一些数据项。这块内存叫做方法的栈帧(stack frame)。
    1.栈帧包含的内存保存如下内容。
            1.返回地址,也就是在方法推出的时候继续执行的位置。
            2.这些参数分配的内存,也就是方法的值参数,或者还可能是参数的数组(如果有的话)。
            3.各种和方法调用相关的其他管理数据项
    2.在方法调用时,整个栈帧都会压入栈。
    3.在方法推出的时候,整个栈帧都会从栈上弹出,弹出栈帧有时候也叫做 栈展开 (unwind).
 
 
 
5.16 递归 要理解递归看看栈帧
    除了调用其他方法,方法也可以调用自身,这叫做递归。
  1. classProgram
  2. {
  3. publicstaticvoidCount(int num)
  4. {
  5. if(num ==0)
  6. {
  7. return;
  8. }
  9. Count(num-1);
  10. Console.WriteLine(num);
  11. }
  12. staticvoidMain(string[] args)
  13. {
  14. Count(2);
  15. }
  16. }
17. 输出的结果 1 2
 
 
 
 





  相关解决方案