有人能举例说明在C#代码中实际使用"不安全"和"修复"的好时机吗?我以前玩过它,但从来没有真正找到它的好用.
考虑这段代码......
fixed (byte* pSrc = src, pDst = dst) { //Code that copies the bytes in a loop }
与简单使用...相比
Array.Copy(source, target, source.Length);
第二个是.NET Framework中的代码,第一部分是从Microsoft网站复制的代码,http://msdn.microsoft.com/en-us/library/28k1s2k6(VS.80).aspx.
内置的Array.Copy()比使用Unsafe代码要快得多.这可能只是因为第二个只是更好的编写,第一个只是一个例子,但你真的甚至需要使用不安全/固定代码的什么样的情况?或者,这个可怜的网络开发人员是否在弄乱他的头脑?
它与非托管代码互操作很有用.传递给非托管函数的任何指针都需要修复(也就是固定)以防止垃圾收集器重新定位底层内存.
如果您正在使用P/Invoke,那么默认的编组器将为您固定对象.有时需要执行自定义编组,有时需要将对象固定的时间超过单个P/Invoke调用的持续时间.
我用过不安全的块来操作Bitmap数据.原始指针访问速度明显快于SetPixel/GetPixel.
unsafe { BitmapData bmData = bm.LockBits(...) byte *bits = (byte*)pixels.ToPointer(); // Do stuff with bits }
"固定"和"不安全"通常在进行互操作时或需要额外性能时使用.IE浏览器.String.CopyTo()在其实现中使用unsafe和fixed.
reinterpret_cast样式行为
如果你有点操纵,那么这可能非常有用
许多高性能哈希码实现使用UInt32作为哈希值(这使得移位更简单).由于.Net需要Int32用于您希望快速将uint转换为int的方法.由于重要的不是实际值,只需要保留值中的所有位,需要重新解释.
public static unsafe int UInt32ToInt32Bits(uint x) { return *((int*)(void*)&x); }
请注意,命名是在BitConverter.DoubleToInt64Bits上建模的
继续在散列静脉中,将基于堆栈的结构转换为字节*允许轻松使用每字节散列函数:
// from the Jenkins one at a time hash function private static unsafe void Hash(byte* data, int len, ref uint hash) { for (int i = 0; i < len; i++) { hash += data[i]; hash += (hash << 10); hash ^= (hash >> 6); } } public unsafe static void HashCombine(ref uint sofar, long data) { byte* dataBytes = (byte*)(void*)&data; AddToHash(dataBytes, sizeof(long), ref sofar); }
不安全(从2.0开始)允许你使用stackalloc.这在需要一些小的可变长度数组(如临时空间)的高性能情况下非常有用.
所有这些用途都将坚定地存在于"只有当你的应用程序确实需要性能"时,因此在一般使用中是不合适的,但有时你确实需要它.
当你希望与一些有用的非托管函数(有许多)交互时,需要使用fixed来获取c样式的数组或字符串.因此,它不仅是出于性能原因而且是在互操作场景中的正确性.