Предположим, что у меня есть указатель символа типа* к строке unicode, и я знаю длину:
char* _unmanagedStr;
int _unmanagedStrLength;
и у меня есть 2 способа преобразовать его в строку.NET:
Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);
и
new string(_unmanagedStr, 0, _unmanagedStrLength);
В моих тестах оба вызова дают мне точно тот же результат, но new string()
похож 1.8x времена быстрее, чем Marshal.PtrToStringUni()
.
Почему то различие в производительности? Есть ли между обоими какое-либо другое функциональное различие?
Судя по доступному исходному коду (Rotor), конструктор System.String (Char *) использует сильно оптимизированный путь кода через CtorCharPtr (), он выделяет строка с FastAllocateString (). Marshal.PtrToStringUni () следует совершенно по другому пути кода, он написан на C ++ и, похоже, дважды копирует строку без преимущества «быстрого распределителя».
Ясно, что над этим работал не один и тот же программист. Почти наверняка даже не одна и та же команда, поскольку код соответствует другой модели программирования. Ближайший из общих менеджеров, вероятно, был на четыре уровня выше.
Не уверен, насколько это будет полезно, воспользуйтесь быстрым. В Windows может возникнуть подобное исключение.
Второй несовместим с CLS, требует небезопасного кода и может иметь неопределенное поведение, поэтому, вероятно, он быстрее. Также необходимо закрепить указатель на неуправляемый адрес, иначе сборщик мусора может перераспределить его, что приведет к более загроможденному коду. Если вы не определили, что это узкое место для вашего приложения, вы, вероятно, захотите использовать функцию PtrToStringUni .