C#是一种高级语言,他其中一个特性就是Managed code的概念。整个C#的程序都是在.NET runtime里运行的,这个设计能够有效防止程序员一些错误的编程,有效提高了程序的稳定性。但如果我们有时候真的需要直接操作内存,或者想写一些高效的代码,是不是就没办法了呢?实际上,C#并没有完全去掉对指针和底层memory操作的支持。可是如果要想使用指针的话,就必须使用unsafe这个关键字。unsafe可以使用在一个方法上:
[code:c#]unsafe int GetSomeNumber() { //code that can use pointers }
[/code]
当然,你也可以使用unsafe将真个类包起来:
[code:c#]unsafe class MyClass { }
[/code]
同样的,也可以将类中的某个属性标记为unsafe
[code:c#]class MyClass { unsafe int* pX; }
[/code]
或者你可以只将代码中的某一段包起来
[code:c#]void MyMethod() { //code that doesn't use pointers unsafe { } }
[/code]
可是对于方法内部的本地变量,是不可以标识为unsafe的:
[code:c#]int MyMethod() { unsafe int *pX; //WRONG }
[/code]
如果想在方法内部使用一个指针性的本地变量的话,就要将该方法标识为unsafe或者在unsafe block内部声明该变量。最后,你只要在project properties里面的Build页面把allow unsafe code选项勾上就可以了。C#中关于指针的语法和C/C++差不多,在这里就不再详述了。唯一区别是在声明指针变量上面,C++是int *px, *py;而C#是int* px,py;在C#中*是跟随类型而不是跟随变量名的。
类成员的指针
在C#中,指向类的指针是不允许的。因为C#的garbage collector并没有维护指针的信息,指针指向的内存有可能在程序运行的时候被回收,造成意想不到的后果。可是我们有没有办法将指针指向类中的变量呢?比如我们有一个如下的类:
[code:c#]class MyClass { public long x; public float F; } MyClass myObject = new MyClass(); long* p: = &(myObject.X); float* pF = &(myObject.F);
[/code]
如果你尝试编译以上代码的话你就会发现编译器会返回一个编译错误。原因就是因为在C#中,类是放在heap上的,garbage collector有可能随时将一个类移到新的地方,使得本来的指针指向了一个错误的位置。要解决这个问题,就要使用fixed关键字。将以上代码做以下的修改:
[code:c#]MyClass myObject = new MyClass(); fixed(long* pL = &(myObject.X)) { //do something }
[/code]
使用了fixed关键字,garbage collector就不会将该类移动到别处。fixed关键字还可以有以下用法:
[code:c#]fixed(long *pL = &(myObject.X)) fixed(float *pF = &(myObject.F)) { }
[/code]
或者
[code:c#]fixed(long * pX=&(myObject.X), px2=&(myObject2.X)) { }
[/code]