C#中方法及参数的类型解析
一、方法中参数的类型
1.in型参数
int 型参数通过值传递的方式将数值传入方法中,即我们在Java中常见的方法。
2.ref型参数
该种类型的参数传递变量地址给方法(引用传递),传递前变量必须初始化。
该类型与out型的区别在与:
1)ref 型传递变量前,变量必须初始化,否则编译器会报错,而out型则不需要初始化。
2)ref 型传递变量,数值可以传入方法中,而out型无法将数据传入方法中。换言之,ref 型有进有出,out 型只出不进。
3.out 型参数
与 ref 型类似,仅用于传回结果。
4.注意事项
1)out型数据在方法中必须要赋值,否则编译器会报错。
eg:如下图若将代码中的sum1方法的方法体
改为 a+=b; 则编译器会报错。原因:out 型只出不进,在没给 a 赋值前是不能使用的
改为 b+=b+2; 编译器也会报错。原因:out 型数据在方法中必须要赋值。
2)重载方法时若两个方法的区别仅限于一个参数类型为ref 另一个方法中为out,编译器会报错
eg:若将下面的代码中将方法名 vsum1 改为 sum(或者将方法名 sum 改为 sum1),编译器会报错。
Error 1 Cannot define overloaded method ‘sum’ because it differs from another method only on ref and out
原因:参数类型区别仅限于为 ref 与为 out 时,若重载对编译器而言两者的元数据表示完全相同。
class C{
//1. in型参数
public void sum(int a, int b) {
a += b;
}
//2. ref型参数
public void sum(ref int a, int b) {
a += b;
}
//3. out型参数
public void sum1(out int a, int b){
a = b+2;
}
public static void Main(string[] args) {
C c = new C();
int a = 1, b = 2;
c.sum(a,b);
Console.WriteLine("a:{0}", a);
a = 1; b = 2;
c.sum(ref a, b);
Console.WriteLine("ref a:{0}", a);
a = 1; b = 2;
c.sum1(out a, b);
Console.WriteLine("out a:{0}", a);
}
}
输出结果:

从代码也可以看出,int 型参数为值传递,所以当将变量 a 传入方法时,变量 a 的值并不会发生变化。而 ref 型参数,由于是引用传递,将变量的值和地址都传入方法中故变量值改变。out 型无法将变量的值传入。但可以将变量的地址传入并为该地址上的变量赋值。
5.ref 和 out 的区别
一个用关键字 ref 标示,一个用 out 标示。
牵扯到数据是引用类型还是值类型。
一般用这两个关键字你是想调用一个函数将某个值类型的数据通过一个函数后进行更改。传 out 定义的参数进去的时候这个参数在函数内部必须初始化。否则是不能进行编译的。ref 和 out 都是传递数据的地址,正因为传了地址,才能对源数据进行修改。
一般情况下不加 ref 或者 out 的时候,传值类型的数据进去实际上传进去的是源数据的一个副本,也就是在内存中新开辟了一块空间,这里面存的值是与源数据相等的,这也就是为什么在传值类型数据的时候你如果不用 return 是无法修改原值的原因。但是你如果用了 ref,或者 out,这一切问题都解决了,因为他们传的是地址。
out 比起 ref 来说,还有一个用法就是可以作为多返回值来用,都知道函数只能有一个返回值,C#里,如果你想让一个函数有多个返回值,那么OUT能很容易解决。
二、对于复杂引用类型参数传递的控制
所谓复杂,是参数是数组或集合类型,或者参数包含这些类型数据,这种情况下上面的方法不能保证参数数据不被修改,因为即使对象为只读的,但是对象中的数组或集合字段(属性)还是可以修改的。
1.集合参数(包含集合字段的引用参数也一样)
.net 4.5以前版本可以使用不包含修改集合元素方法的接口来代替具体集合类型。例如使用IEnumerable<T>接口代替List<T>。4.5版本可以直接使用IReadOnlyCollection接口或实现该接口的集合类型。
2.数组参数
没有好的办法保护数组类型参数不被修改,所以尽量避免使用数组类型作为方法参数,除非用到可选参数时候。
三、扩展方法
扩展方法可以实现在不需要修改目标类,也不需要继承目标类的情况下为其添加一个方法。规则:
1、扩展类必须为静态类,扩展方法必须为静态方法。
2、扩展方法的第1个形参开头必须使用 “this” 关键字然后再填写扩展的目标类。
3、如果需要接收参数则从第2个参数开始算起,第1个参数在真正调用方法时是隐藏的。
public static class ExtensionString{
//向 String 类扩展一个统计单词数量的方法
public static int CountWord(this String str) {
return str.Split(' ').Length;
}
}
class MainClass{
public static void Main(string[] args) {
Console.WriteLine("单词数量:" + "Hello World".CountWord()); //没有参数
}
}
想要观看更多课程请点击:
https://bycwedu.vipwan.cn/promotion_channels/630597732