Marshal.PtrToStringUni () vs new String ()?
-
19-09-2019 - |
Pergunta
Suponha que eu tenho um ponteiro do tipo char * a seqüência de caracteres Unicode, e eu sei que o comprimento:
char* _unmanagedStr;
int _unmanagedStrLength;
e eu tenho 2 maneiras de convertê-lo para string NET:
Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);
e
new string(_unmanagedStr, 0, _unmanagedStrLength);
Em meus testes, ambas as chamadas me dá exatamente o mesmo resultado, mas o new string()
é como 1,8x vezes mais rápido que Marshal.PtrToStringUni()
.
Por que é que a diferença de desempenho? Existe alguma outra diferença funcional entre os dois?
Solução
A julgar a partir do código fonte disponível (Rotor), o System.String (Char *) construtor usa um caminho de código altamente otimizado através CtorCharPtr (), atribui a string com FastAllocateString (). Marshal.PtrToStringUni () segue um caminho de código totalmente diferente, que é escrito em C ++ e parece ser copiar a cadeia duas vezes, sem o benefício de um "alocador rápido".
Claramente, não é o mesmo programador trabalhou sobre este assunto. Quase certamente nem mesmo a mesma equipe desde que o código se encaixa um modelo de programação diferente. O gerente mais próximo em comum era, provavelmente, quatro níveis acima.
Não tenho certeza como isso seria útil, use a um rápido. Percalços geraria um tipo semelhante de exceção no Windows.
Outras dicas
O segundo não é compatível com CLS, requer código inseguro e pode ter comportamento indeterminado e é por isso provavelmente é mais rápido. Há também uma necessidade de pin o ponteiro para o endereço não gerenciado ou o coletor de lixo pode realocá-lo que leades a um código mais desordenado. A menos que você determinou que este é um gargalo para a sua aplicação, você provavelmente vai querer usar o função PtrToStringUni .