1:JIT(即时编译)。一个方法在第一次调用时JIT会把改方法的IL代码转换成CPU指令,再次调用该方法时就只需执行对应的指令。方法第一次被调用的过程大致是:1获得方法的IL代码;2:分配内存;3:将IL代码转换成CPU指令存在2分配的内存中;4:将方法表中对应该方法的指针指向2分配的内存;5:跳转到2分配的内存执行其中的指令,即该方法的CPU指令。
2:as的性能高于is。Is的作用是判断当前类型与目标类型是否兼容,即是否是同一类型或者目标类型是当前类型的父类型。强制类型转换也要判断类型的兼容性,如果不兼容就抛出一个类型转换异常,如果你的代码类型转换用Is+强制类型转换就做了两次兼容性判断,而as只有一次类型转换。
3:C#中的int对应FCL中的Int32,long对应FCL中的Int64,同一类型,64位CPU所需存储的空间是32位CPU的2倍。
4:string是引用类型,常量字符串都存在字符串池中,如果一个字符串在代码中多次出现,那么这些都是对字符串池的引用,string s="a"+"b";只分配了一次内存,编译器会直接将其编译成string s="ab";s是对字符串池中ab的引用。
5:大量字符串的拼接用StringBuilder,少量则用字符串相加,能用+=则更好,string.format的效率是低下的,它的内存其实是params object[] +StringBuilder,params也是低效的,字符串相加,或是取其中的一部分都是要重新分配内存,然后将对应的字符串存入。FCL大部分代码都是用C#写的,而操作字符串这一块用的是非托管代码写的,处于对性能的考虑。
6:别看到new就以为会在托管堆中分配内存,值类型的变量就是分配中线程栈上的,结构体虽然可以用new,但是编译器推断出它是值类型,就会按照值类型的处理,当然IL代码中是没有newobj指令的。
7:静态类被编译成sealed abstract类型,所以他不能被继承,不能被实例化,所以他的属性和方法都是属于类型的,没有属于对象的,它必须直接继承Object。
8:const和readOnly的区别,IL代码中存的是const变量的值,而不是引用,所以修改是不可能的,如果一个DLL只引用了另一个DLL中的一个const变量,那么这个DLL是不会被引用的,因为编译的时候就知道变量的值了,所以在运行的时候也不会分配内存,readonly表示你不能修改它的指向,但是可以修改它所指向变量的值。
9:泛型,C#中的泛型和C++的模版区别在于引用类型,C++模版会每一种类型都会生成一个新的类型(引用类型是不会的),而C#泛型中,引用类型用的是同一个类型,只有值类型用的是不同的类型。因为引用都是一个指针的引用,而值类型存储所需的空间是不同的。在C++中有模版半特化,将T 半特化成void*,这样指针类型就不用再生成一套代码了
其他基础知识,请看这篇博客:这些天写的技术微博
作者:陈太汉