Маршал.PtrToStringUni() против new String()?
-
19-09-2019 - |
Вопрос
Предположим, у меня есть указатель типа char * на строку в юникоде, и я знаю длину:
char* _unmanagedStr;
int _unmanagedStrLength;
и у меня есть 2 способа преобразовать его в .NET string:
Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);
и
new string(_unmanagedStr, 0, _unmanagedStrLength);
В моих тестах оба вызова дают мне точно такой же результат, но new string()
примерно в 1,8 раза быстрее, чем Marshal.PtrToStringUni()
.
Почему такая разница в производительности?Есть ли еще какое-то функциональное различие между ними обоими?
Решение
Судя по доступному исходному коду (Rotor), Система.Конструктор String(Char*) использует сильно оптимизированный путь к коду через CtorCharPtr(), он выделяет строку с помощью FastAllocateString().Маршал.PtrToStringUni() следует совершенно другому пути кода, он написан на C ++ и, похоже, копирует строку дважды, без использования "быстрого распределителя".
Очевидно, что над этим работал не один и тот же программист.Почти наверняка это даже не одна и та же команда, поскольку код соответствует другой модели программирования.Ближайший общий менеджер был, вероятно, на четыре уровня выше.
Не уверен, насколько это было бы полезно, используй быстрый вариант.Сбои будут генерировать исключения аналогичного типа в Windows.
Другие советы
Второй не совместим с CLS, требует небезопасного кода и может иметь неопределенное поведение, поэтому, вероятно, он быстрее.Существует также необходимость в булавка указатель на неуправляемый адрес или сборщик мусора может перераспределить его, что приведет к более загроможденному коду.Если вы не определили, что это узкое место для вашего приложения, вы, вероятно, захотите использовать ПтрТоСтрингУни функция.