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

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

Interoperabilidade COM

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.

Observação de cuidadoCuidado

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

Atributos direcionais

Interop Marshaling

Outros recursos

Comportamento de empacotamento padrão