ref和out达到效果,传递的是参数的地址而不是参数本身.
从CLR的角度看,ref和out完全一致.会生成相同的IL代码.元数据几乎完全一致,只有一个bit除外,以区分这两种情况.
为值类型使用out和ref,等同于为引用类型使用传值的方式(普通的方式).
以引用的方式传递参数,需要参数类型和方法签名的类型完全相同,哪怕是基类也不行
如果传递的不是null,会有一定的性能损失.因为在底层中会在堆上分配一个数组,最后垃圾回收.
IL中方法会被添加ParamArrayAttribute属性.编译器会优先查找没有可变参数的方法,其次才会查找可变参数的方法.
声明方法的参数类型时,尽量是最弱的类型,最好是接口而不是基类.比如使用UEnumerable<T>而不是List<T>
对于方法的返回类型最好声明为最强的类型.(子类)
1. 针对源代码中的每一个属性,编译器会在属性名之前添加get_和set_前缀,自动生成这些方法.C#内建了对属性的支持.此外,编译器还会生成属性定义的源数据,简建立属性和getset方法的联系.但是CLR不适用这些元数据,编译器会使用这些信息.
2.Public String Name{get;set;}是自动实现的属性,简称AIP.AIP的支持字段的名称是有编译器决定的,每次重新编译,都可能修改这个名字,在序列化和反序列化中就有问题.AIP属性必然是可读和可写的,不能显示实现一个访问器方法,让另一个自动实现,如public string Test { get { return ""; } set; },这样是不可以的.
3. 属性不能作为out 和ref参数传递给方法,字段可以.
如果源代码中定义了多个匿名类型,而且这些类型的结构相同,属性名称类型相同,顺序相同,就会只创建一个匿名类型,多个实例.
匿名类型还可以这样Var test=new {dt.Name,dt.Year}.根据赋值的字段的名字类型确定生成的属性的类型.
同样,匿名数组也是可以的.匿名类型经常和Linq配合一起来使用.
匿名类型无法传到方法的外部.
匿名类型创建之后属性都是只读的.和Tuple元组是一样的.
索引器.还可以重载,可定义多个索引器.IndexerNameAttribute可以自定义索引器生成的默认名字(Item).String.Chars就是这样的一个例子.
CLR并不区分有参属性和无参属性.
对于简单的getset访问器方法,JIT编译器会将代码内联,这样使用属性跟字段比就没有性能损失.JIt在调试时是不会内联的,发布时才可能会内联.
1. 事件参数按照规则继承自EventArgs
2. 对于一个事件,编译器会生成一个Private事件字段,以及Add和Remove方法,维护登记的方法列表.Remove一个不存在的注册方法时,是不会报错的.add的时候是会重复注册的,不会坚持是否已经存在.
3. 如果一个类实例登记了某一个事件,那么这个实例就不会被回收.所以如果类型要实现Dispose方法,就应该在这里取消事件的注册.
4. 开发人员可以显示实现事件,使用的是EventSet类.