C#基础备忘3-方法
时间:2010-12-28 来源:金山崟霸
2. 局部变量和实例字段的区别:
3. var 关键字只是语法上的速记,表示任何可以从初始化式 的右边推断出的类型。 var 只能在包含初始化式的局部变量 声明中使用,并且一旦编译器推断出类型,它就是固定且不能更改的。 var 关键字并不会改变 C# 的强类型性质。
4. 与 C/C++ 不同,在 C# 中,不论嵌套级别如何,都不能在第一个名称的有效范围内 声明另一个同名的局部变量 。
5. 声明常量时必须初始化,在类型之前 需要加关键字 const ,初始化值必须是能在编译期决定的,可以使 null ,但不能是某对象的引用,因为对象的引用是在运行时决定的 。
6. 方法调用时的动作顺序: 1. 当前方法的执行在调用点被挂起; 2. 控制转移到被调用方法; 3. 被调用方法执行直到完成; 4. 控制回到发起调用的方法。
7. 方法返回值会被插入到调用代码中发起调用的表达式所在的位置。“ return; ”这种形式的返回语句只能用于声明为 void 类型的方法,它的作用是可以在任何时候退出方法。
8. 使用值参数时,通过将实参的值复制给形参的方式传递到方法中,方法被调用时,操作系统会在栈中为形参分配空间,然后复制实参到形参 。如果是引用类型,那么引用 会被复制,实参和形参都引用堆中的同一个对象 ,方法结束后,实参的数据会被方法的行为所改变;如果是值类型,会产生一个独立的数据项,方法结束后实参的值不会受方法行为的影响。但要注意,若为引用类型,在方法中改变了引用所指向的对象(即改变了引用的值),则后续的操作将不会反映到实参上,因为形参只是实参的一个副本,方法结束后将被销毁,不能用于信息回传,若想实现此效果,则要使用ref参数 (这与C/C++的值传递机制类似) 。
9. 使用 ref 参数,必须在方法的声明 和调用 中都使用 ref 修饰符;实参必须是变量 ,且用作实参前必须被赋值 ,如果是引用类型变量,可以赋值为一个引用或 null 。
10. ref 参数的特征: 1. 不在栈中为形参分配新的内存 ; 2. 形参的名称相当于是实参变量的别名,引用与实参相同的内存位置 。方法执行之后,形参的名称已经失效,但方法内对形参的任何改变都会体现在实参上 ( 类似于 C++ 的引用 ) 。
11. out 参数用于从方法体内把数据传出 到调用代码 ,类似 ref 参数。必须在声明和调用中都使用修饰符 out ,参数同样必须是变量 ,不能是其他表达式类型。与 ref 参数不同的是:在方法内部, out 参数在被读取之前 必须被赋值 ,这意味着参数的初始值无关紧要,而且不必在方法调用之前为实参赋值,但每个 out 参数在方法返回之前必须被赋值。
12. 方法内的代码在读取 out 参数之前必须对其写入 ,所以不可能使用 out 参数把数据传入方法 。
13. 在一个参数列表中只能有一个参数数组,如果有,它必须是列表中的最后一个 。声明一个参数数组必须要使用 params 修饰符,且在数据类型后放置一组空的方括号,如: void ListInts( parama int[] inVals ){ } , inVals 可以代表 0 个或多个 实参。 注意:数组是一个引用类型,所以它的所有数据项都保存在堆 中 。
14. 上面函数的调用可以采用两种形式,如: ListInt( 10, 20, 30 ); 或 int[] intArray = {1, 2, 3}; 。第一种形式叫做延伸式,在调用中使用分离 的实参,编译期会接受实参列表,用它们在堆 中创建一个数组并用实参列表初始化 ;把数组的引用 保存到栈 中的形参 里;如果在对应的形参数组的位置没有实参,编译期会创建一个有 0 个元素的数组 来使用。
15. 当参数数组在堆中被创建时,实参的值 被复制到数组中,这类似于值参数,如果数组参数是值类型,那么值被复制,实参不受方法内不影响;如果数组参数是引用类型,那么引用被复制,实参应用的对象会受到方法内部的影响。
16. 如果使用单一的数组变量作为实参传递,编译器会使用传入的数组而不是新创建一个。在声明中必须加上 修饰符 params ,但在调用时不允许 有修饰符。
17. 在栈中会保存局部变量和方法的参数,当一个方法被调用时,在栈顶 分配了一块内存用于保存一定数量与方法相关的数据项,这块内存叫方法的栈帧。
栈帧保存以下内容:
返回地址 ( 方法退出后在哪儿继续执行 ) ;
分配内存的参数 ;
与方法调用相关的其他各种数据项 。
18. 方法被调用时,它的整个 栈帧被压入栈中。方法退出时,它的整个 栈帧被从栈中弹出。弹出一个栈帧有时也叫释放栈。
19. 方法签名包含:名称、参数的数目、参数的数据类型和顺序、参数修饰符,返回类型不是 方法签名的一部分。
20. C# 中如果存在方法重载,会根据其引用的类型 (reference type) 来调用对象的方法,而不是根据对象的类型( instance type )来调用,另外,如果通过未加说明的 null 来调用方法,编译器会以继承层次中最下层子类 的类型 来调用。