Marshal.PtrToStringUni()与new String()有何区别?

7
假设我有一个指向Unicode字符串的char*指针,并且我知道它的长度:
char* _unmanagedStr;
int _unmanagedStrLength;

我有两种方法将它转换为.NET字符串:

Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);

并且

new string(_unmanagedStr, 0, _unmanagedStrLength);

在我的测试中,这两个调用都给我完全相同的结果,但是new string()Marshal.PtrToStringUni()更快约1.8倍。
这种性能差异是什么原因? 它们之间是否还有其他功能上的区别?
2个回答

9
根据可用的源代码(Rotor),System.String(Char*)构造函数通过CtorCharPtr()使用高度优化的代码路径,使用FastAllocateString()分配字符串。Marshal.PtrToStringUni()遵循完全不同的代码路径,它是用C++编写的,看起来复制了两次字符串,没有使用“快速分配器”的好处。
显然,这不是同一位程序员编写的。几乎可以确定不是同一个团队,因为代码适合不同的编程模型。最接近的共同经理可能在四个级别之上。
不确定如何有所帮助,请使用快速版本。在Windows上会生成类似的异常。

8
第二种方法不符合CLS,需要使用不安全的代码,并且可能具有不确定的行为,这也是为什么它可能更快的原因。还需要将指针固定到未托管地址,否则垃圾回收器可能会重新分配它,导致代码更加混乱。除非您确定这是应用程序的瓶颈,否则您可能希望使用PtrToStringUni函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接