CLR via C# 学习笔记(2012/3/4)

第九章 参数

参数一般指的是方法名中的形参,而我们一般定义的方法中的参数也就是public void SomeMethod(string a,int b)中的string和int类型参数,而c#可以定义可选参数和命名参数,也就是在定义参数列表时,给参数定义一个默认值,例如:public static void M(int x = 9, string s = "A", DateTime dt = default(DateTime), Guid guid = new Guid()),这种方式一般使用不多,就我自己而言。

隐式类型的局部变量——var

var关键字定义的局部变量在编译时进行类型推断,这样能够在使用复杂类型时,减少代码的打字量,同是var也常用于IEnumable类型的Lambda表达式。但是var不能用于定义形参类型,因为编译器必须根据传入的参数类型来判断所调用的方法,如果使用var,编译器就不知道调用的是什么方法了


参数的传递方式

调用方法时,参数是以pass by value方式来传递参数的,无论参数是值类型还是引用类型,都是传递值。如果是值类型,就传递具体的数值,也就是一份副本,而该副本在方法内部改变了,不影响方法外的原变量的值,而引用类型传递的也是值,不过是引用地址的一份副本,由于指向的都是同一个地址,那么方法内改变了变量,也就会影响方法外的变量了。

不过.net能够以传引用的方式向方向传递参数,使用的是out和ref两个关键字。out和ref对于CLR而言,基本上没有任何区别,IL代码相同,元数据也只有一个bit不一样,这个bit是用而区别使用的是out还是ref。但在C#中是有区别的,out不需要在方法外赋值,但在方法返回前必须给参数赋值;而ref则相反,必须在调用方法前赋值,但在方法返回前不必要。还有一个地方,就是方法的重载,C#认为参数列表如果只有out和ref对形参修饰的不同,就认为这两个方法是一样的,例如:void Add(ref Point p)和void Add(out Point p)。

对于以传引用的方式,C#编译器要求传递的参数必须为定义的形参类型,不然就编译不通过,

例如:public void Swap(ref Object a, ref Object b)

    {

Object t = b;

b = a;

a = t;

    }

    public void SomeMethod(){

string s1 = "Jeffrey";

string s2 = "Richter";

Swap(s1,s2);

   }

  c#编译器会报错,这主要是为了考虑到类型安全。如果在方法Swap内对a或b赋于其他类型的对象或值,这是可行的,那是由于Object是一切对象的最终基类,但这样就会影响方法外的变量,由于类型不一样了,那调用原本类型的字段或方法就一定会出错,所以c#编译器为了类型安全,就强制使用传值时要使用定义的参数类型。

可变数量参数

可变数量参数,实则上就是一个数组,只是这个数组参数用params关键字修饰。编译器查找具体调用方法时,先检查参数没有使用params的方法,如果找到就调用该方法,如果找不到,则查找使用params的方法。

调用一个可变参数的方法时,会造成一些性能损失。因为数组对象必须在堆上分配内存,数组元素的初始化,并且在方法调用返回时,必须垃圾回收。为了降低性能的损失,一般会重载几个没有使用params的方法。


参数和返回类型的指导原则

一般为了扩大使用范围,声明参数类型时,最好尽量指定最弱的类型,最好是接口而不是基类。

相反,一般最好是将方法的返回类型声明为最强的类型。但如果希望保持一定的灵活性,返回类型可以选择一个较弱的类型,比如集合类型,可以选择IList<T>而不是List<T>作为返回类型,这样比较灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值