4.C#基础篇-->变量

一.前言

  变量的类型划分即内存中的存放位置如图:

  

  变量的生命周期如图:

  

  

二.实参和形参

     形参是声明在方法的参数列表中。和方法体中的其他变量不同,参数在方法体外定义并在方法体开始之前初始化。

   实参是用于初始化形参的表达式或者变量。当代码调用一个方法时,形参的值必须在方法体执行之前被初始化。

   

三.值参数

  什么是值参数?默认类型的参数称为值参数。

  值参数代码举例如图:

  

  值参数特征:

  1.在方法被调用之前,做为实参的a1和a2已经在栈中了。

  2.随着方法的开始,系统在栈中为形参分配空间,并从实参复制。因为a1是引用类型,所以引用被复制,结果实参和形参都引用堆中的同一个对象;因为a2是值类型,所以值被复制,产生一个独立数据项;

  3.在方法的结尾,f2和对象f1的字段都被加上5。

  4.方法执行后,形参被从栈中弹出。a2值类型,它的值不受方法行为影响;a1,引用类型,但它的值被方法的行为改变了;

  

四.引用参数

     什么是引用参数?使用引用参数时,必须在方法的声明和调用中都使用ref修饰符。实参必须是变量,在用作实参前必须被赋值。如果是引用类型,可以赋值一个引用或者NULL。

   下图阐明了引用参数的声明和调用语法:

  

  引用参数代码举例如图:

  

  引用参数特征:

  1.不在栈中为形参分配新的内存。

  2.形参的名称相当于实参变量的别名,引用与实参相同的内存位置。

  既然形参和实参引用相同的内存位置,则在方法执行期间,形参所做的任何改变在方法完成之后通过实参变量都是可见的。

  

 

五.输出参数

  什么是输出参数?用于从方法体内把数据传出到调用代码。必须在方法的声明和调用中都使用out修饰符。实参必须是变量,在用作实参前非必须被赋值。但是在方法体中实参在被读取之前必须被赋值,每个输出参数在方法返回之前必须被赋值。

  下图阐明了输出参数的声明和调用语法:

  

  输出参数代码举例如图:

  

  输出参数特征:

  1.不在栈中为形参分配新的内存。

  2.形参的名称相当于实参变量的别名,引用与实参相同的内存位置。

  既然形参和实参引用相同的内存位置,则在方法执行期间,形参所做的任何改变在方法完成之后通过实参变量都是可见的。

  

六.参数数组

  什么是参数数组?允许零个或者多个实参对应一个特殊的形参。重点如下:

  1.参数列表中只能有一个参数数组。

  2.如果有,必须是在列表的最后一个。

  3.在数据类型前,使用params修饰符。

  4.在数据类型后,放置一个方括号。

  5.由于数组是引用类型,所以它的所有数据项都存放在堆中。

  

  如何调用拥有数组参数的方法?有两个方法提供实参:

  1.逗号分隔的该数据类型的元素的列表。

  

  2.一个该数据类型元素的一维数组。

  

  第一种调用可以被称为延伸式。这种形式在调用中使用分离的实参。ListInts的声明可以匹配下面所有的方法调用。

  

  在使用一个为参数数组分离实参的调用时,编译器做了下面的事:

  1.接受实参列表,用它们在堆中创建并初始化了一个数组。

  2.把数组的引用保存在栈中的形参里。

  3.如果在对应的形参数组的位置没有实参,编译器会创建一个有零个元素的数组来使用。

  

  1.方法调用前,三个实参已经在栈中。

  2.在方法的开始,三个实参被用于初始化堆中的数组,并且数组的引用被赋值给了形参invals。

  3.在方法的内部,方法对数组中的值进行修改。

  4.在方法结束后,形参失效。

  关于参数数组,重点是当数组在堆中被创建的时候,实参的值被复制到数组中。这方面它想值参数。

  1.如果数组参数是值类型,那么值被复制,实参不受方法影响。

  2.如果数组参数是引用类型,那么引用被复制,实参会受到方法的影响。

  

  第二种调用,即数组做为参数。这时候编译器会使用你的数组,而不是创建一个。

  

  这里要注意,数组是一个引用类型,所以myarr的元素被修改了。

posted @ 2014-04-18 01:36  荒古禁地2  阅读(545)  评论(2编辑  收藏  举报