Como acessar caracteres em um System::String

Você pode acessar caracteres de um objeto String em chamadas de alto desempenho para funções não gerenciadas que aceitam strings wchar_t*. O método produz um ponteiro interior para o primeiro caractere do objeto String. Esse ponteiro pode ser manipulado diretamente ou fixado na memória e passado para uma função que espera uma cadeia de caracteres wchar_t normal.

Importante

Ponteiros internos em objetos String devem ser tratados como const. Um String objeto é considerado imutável e alterar seu conteúdo pode desestabilizar o runtime. Para obter mais informações, consulte as práticas recomendadas de código não seguro – 17. Mutações de cadeia de caracteres.

Exemplos

PtrToStringChars retorna um Char, que é um ponteiro interno (também conhecido como um byref). Dessa forma, ele está sujeito à coleta de lixo. Não é necessário fixar esse ponteiro a menos que você vá passá-lo para uma função nativa.

Considere o código a seguir. A fixação não é necessária porque ppchar é um ponteiro interior e, se o coletor de lixo mover a cadeia de caracteres para a qual ele aponta, também atualizará ppchar. Sem um pin_ptr (C++/CLI), o código funcionará e não terá o potencial impacto de desempenho causado pela fixação.

Se você passar ppchar para uma função nativa, ela precisará ser um ponteiro de fixação; o coletor de lixo não poderá atualizar nenhum ponteiro no quadro de pilha não gerenciado.

// PtrToStringChars.cpp
// compile with: /clr
#include <vcclr.h>
using namespace System;

int main() {
   String ^ mystring = "abcdefg";

   interior_ptr<const Char> ppchar = PtrToStringChars( mystring );

   for ( ; *ppchar != L'\0'; ++ppchar )
      Console::Write(*ppchar);
}
abcdefg

Este exemplo mostra onde a fixação é necessária.

// PtrToStringChars_2.cpp
// compile with: /clr
#include <string.h>
#include <vcclr.h>
// using namespace System;

size_t getlen(System::String ^ s) {
   // Since this is an outside string, we want to be secure.
   // To be secure, we need a maximum size.
   size_t maxsize = 256;
   // make sure it doesn't move during the unmanaged call
   pin_ptr<const wchar_t> pinchars = PtrToStringChars(s);
   return wcsnlen(pinchars, maxsize);
}

int main() {
   System::Console::WriteLine(getlen("testing"));
}
7

Um ponteiro interior tem todas as propriedades de um ponteiro C++ nativo. Por exemplo, você pode usá-lo para percorrer uma estrutura de dados vinculada e fazer inserções e exclusões usando apenas um ponteiro:

// PtrToStringChars_3.cpp
// compile with: /clr /LD
using namespace System;
ref struct ListNode {
   Int32 elem;
   ListNode ^ Next;
};

void deleteNode( ListNode ^ list, Int32 e ) {
   interior_ptr<ListNode ^> ptrToNext = &list;
   while (*ptrToNext != nullptr) {
      if ( (*ptrToNext) -> elem == e )
         *ptrToNext = (*ptrToNext) -> Next;   // delete node
      else
         ptrToNext = &(*ptrToNext) -> Next;   // move to next node
   }
}

Confira também

Usando interoperabilidade com C++ (P/Invoke implícito)