Copiando e fixando
Quando o empacotamento de dados, o empacotador de interoperabilidade pode copiar ou fixar os dados sendo empacotados. Copiando os dados coloca uma cópia dos dados de um local de memória em outro local de memória. A ilustração a seguir mostra as diferenças entre a cópia de um tipo de valor e a cópia de um tipo passado por referência do gerenciado de memória não gerenciada.
Tipos de valores passados por valor e por referência
Os argumentos do método passados por valor são empacotados para código não gerenciado, como valores na pilha. O processo de cópia é direto. Os argumentos passados por referência são passados como ponteiros na pilha. Tipos de referência também são passados por valor e por referência. Como mostra a ilustração a seguir, os tipos de referência passados por valor são copiados ou fixados.
Tipos de referência passados por valor e referência
Fixando temporariamente bloqueia os dados no local atual de memória, mantendo assim a partir de realocados pelo coletor de lixo do common language runtime. O empacotador fixa de dados para reduzir a sobrecarga de copiar e melhorar o desempenho. O tipo de dados determina se ele é copiado ou fixado durante o processo de empacotamento. A fixação será executada automaticamente durante o empacotamento de objetos, como String, no entanto, você pode também manualmente fixar a memória usando o GCHandle classe.
Classes de Blittable formatado
Formatado blittable classes resolveu o layout (formatada) e a representação de dados comuns em ambos e gerenciados de memória. Quando esses tipos exigem empacotamento, um ponteiro para o objeto na heap é passado diretamente para o receptor. O receptor pode alterar o conteúdo do local de memória que está sendo referenciado pelo ponteiro.
Observação
O receptor pode alterar o conteúdo da memória, se o parâmetro está marcado para Check-Out ou In/Out.Em contraste, o receptor deve evitar alterar o conteúdo quando o parâmetro estiver definido como empacotar como em que é o padrão para tipos blittable formatado.Modificando um objeto em gera problemas quando a mesma classe é exportada para uma biblioteca de tipos e usado para fazer chamadas de apartamento cruzada.
Classes de Blittable não formatado
Formatado não é blittable classes resolveu o layout (formatada), mas a representação de dados é diferente na memória gerenciada e. Os dados podem exigir a transformação sob as seguintes condições:
Se uma classe não-blittable é empacotada por valor, o chamador recebe um ponteiro para uma cópia da estrutura de dados.
Se uma classe não-blittable é empacotada por referência, o chamador recebe um ponteiro para um ponteiro para uma cópia da estrutura de dados.
Se o InAttribute atributo está definido, essa cópia é sempre inicializada com o estado da instância marshaling como necessário.
Se o OutAttribute atributo está definido, o estado é sempre copiado para a instância no retorno, empacotamento, como necessário.
Se ambos os InAttribute e OutAttribute são configurados, ambas as cópias são necessárias. Se o atributo for omitido, o empacotador pode otimizar eliminando copy.
Tipos de referência
Tipos de referência podem ser passados por valor ou referência. Quando eles são passados por valor, um ponteiro para o tipo é passado na pilha. Quando passado por referência, um ponteiro para um ponteiro para o tipo é passado na pilha.
Tipos de referência têm o seguinte comportamento condicional:
Se um tipo de referência é passado por valor, e ele tem membros de tipos de não-blittable, os tipos são convertidos duas vezes:
Quando um argumento é passado para o lado de não gerenciado.
No retorno de chamada.
Para evitar desnecessariamente copiando e conversão, esses tipos são empacotados como em parâmetros. Você deve aplicar explicitamente o InAttribute e OutAttribute atributos de um argumento para o chamador ver as alterações feitas pelo receptor.
Se um tipo de referência é passado por valor, e ele tem apenas os membros de tipos blittable, podem ser fixado durante o empacotamento e quaisquer alterações feitas aos membros do tipo pelo receptor são vistas pelo chamador. Aplicar InAttribute e OutAttribute explicitamente se desejar que esse comportamento. Sem esses atributos direcionais, o empacotador de interoperabilidade não exporta informações direcionais à biblioteca de tipos (ele exporta como In, que é o padrão) e isso pode causar problemas com o empacotamento de cross-apartment COM.
Se um tipo de referência é passado por referência, ele será empacotado como In/Out por padrão.
System. String e System.Text.StringBuilder
Quando os dados são empacotados para código não gerenciado por valor ou referência, o empacotador normalmente copia os dados para um buffer secundário (possivelmente convertendo conjuntos de caracteres durante a cópia) e passa uma referência para o buffer para o receptor. A menos que a referência é um BSTR alocados com SysAllocString, a referência sempre é alocada com CoTaskMemAlloc.
Como uma otimização quando qualquer tipo de seqüência de caracteres é empacotado por valor (como uma seqüência de caracteres Unicode), o empacotador passa o receptor um ponteiro direto para seqüências de caracteres gerenciadas no buffer interno de Unicode em vez de copiá-lo para um novo buffer.
Cuidado |
---|
Quando uma seqüência de caracteres é passada por valor, o receptor nunca deve alterar a referência passada pelo empacotador.Isso pode corromper o heap gerenciado. |
Quando um System.String é passado por referência, o empacotador copia o conteúdo a seqüência de caracteres para um buffer secundário antes de fazer a chamada. Em seguida, copia o conteúdo do buffer em uma nova seqüência no retorno de chamada. Essa técnica garante que a cadeia gerenciada imutável permanece inalterada.
Quando um System.Text.StringBuilder é passado por valor, os passos de empacotador uma referência para o buffer interno da StringBuilder diretamente ao chamador. O chamador e o receptor devem concordar com o tamanho do buffer. O chamador é responsável por criar um StringBuilder de tamanho adequado. O receptor deve tomar as precauções necessárias para garantir que o buffer não está saturado. StringBuilder é uma exceção à regra que são passados por valor de tipos de referência são passados como nos parâmetros por padrão. Sempre é passado como In / out.
Consulte também
Conceitos
Gerenciamento de memória com o empacotador de interoperabilidade