Dela via


Kopiera och fästa

När du samlar in data kan interop-marshallern kopiera eller fästa data som är ordnade. När du kopierar data placeras en kopia av data från en minnesplats på en annan minnesplats. Följande bild visar skillnaderna mellan att kopiera en värdetyp och kopiera en typ som skickas med referens från hanterat till ohanterat minne.

Diagram that shows how value and reference types are copied.

Metodargument som skickas av värdet är ordnade till ohanterad kod som värden i stacken. Kopieringsprocessen är direkt. Argument som skickas av referens skickas som pekare i stacken. Referenstyper skickas också efter värde och referens. Som följande bild visar kopieras eller fästs referenstyper som skickas av värdet:

Diagram showing reference types passed by value and by reference.

När du fäster tillfälligt låss data på den aktuella minnesplatsen, vilket förhindrar att de flyttas av common language runtimes skräpinsamlare. Marshaller fäster data för att minska kostnaderna för kopiering och förbättra prestanda. Typen av data avgör om de kopieras eller fästs under marshallingprocessen. Fästning utförs automatiskt under marshalling för objekt som String, men du kan också fästa minne manuellt med hjälp av GCHandle klassen.

Formaterade blittable-klasser

Formaterade blittable-klasser har fast layout (formaterad) och gemensam datarepresentation i både hanterat och ohanterat minne. När dessa typer kräver marshalling skickas en pekare till objektet i heapen direkt till anropare. Anropare kan ändra innehållet på minnesplatsen som refereras av pekaren.

Kommentar

Anropare kan ändra minnesinnehållet om parametern är markerad som Out eller In/Out. Anropare bör däremot undvika att ändra innehållet när parametern är inställd på marshal som In, vilket är standardvärdet för formaterade blittable-typer. Att ändra ett In-objekt genererar problem när samma klass exporteras till ett typbibliotek och används för att göra anrop mellan lägenheter.

Formaterade icke-blittable-klasser

Formaterade icke-blittable-klasser har fast layout (formaterad) men datarepresentationen skiljer sig i hanterat och ohanterat minne. Data kan kräva transformering under följande villkor:

  • Om en icke-blittable-klass ordnas efter värde, tar anropare emot en pekare till en kopia av datastrukturen.

  • Om en icke-blittable-klass är ordnad efter referens, får anropare en pekare till en pekare till en kopia av datastrukturen.

  • InAttribute Om attributet anges initieras alltid den här kopian med instansens tillstånd, efter behov.

  • OutAttribute Om attributet har angetts kopieras tillståndet alltid tillbaka till instansen vid returen, efter behov.

  • Om både InAttribute och OutAttribute har angetts krävs båda kopiorna. Om något av attributen utelämnas kan marshallern optimera genom att eliminera någon av kopierna.

Referenstyper

Referenstyper kan skickas med värde eller referens. När de skickas av värde skickas en pekare till typen på stacken. När den skickas med referens skickas en pekare till en pekare till typen på stacken.

Referenstyper har följande villkorsstyrda beteende:

  • Om en referenstyp skickas av ett värde och den har medlemmar av icke-blittable-typer konverteras typerna två gånger:

    • När ett argument skickas till den ohanterade sidan.

    • Vid retur från samtalet.

    För att undvika onödig kopiering och konvertering ordnas dessa typer som In-parametrar. Du måste uttryckligen tillämpa attributen InAttribute och OutAttribute på ett argument för att anroparen ska kunna se ändringar som gjorts av anroparen.

  • Om en referenstyp skickas av värde och den bara har medlemmar av blittable-typer, kan den fästas under marshalling och eventuella ändringar som görs i medlemmarna av typen av anroparen ses av anroparen. Använd InAttribute och OutAttribute explicit om du vill ha det här beteendet. Utan dessa riktningsattribut exporterar inte interop marshaller inte riktningsinformation till typbiblioteket (det exporterar som In, vilket är standard) och detta kan orsaka problem med COM-korslagring mellan lägenheter.

  • Om en referenstyp skickas som referens, kommer den att ordnas som In/Out som standard.

System.String och System.Text.StringBuilder

När data är ordnade till ohanterad kod efter värde eller referens kopierar marshaller vanligtvis data till en sekundär buffert (eventuellt konverterar teckenuppsättningar under kopian) och skickar en referens till bufferten till anroparen. Om referensen inte är en BSTR allokerad med SysAllocString allokeras referensen alltid med CoTaskMemAlloc.

Som en optimering när antingen String eller StringBuilder ordnas efter värde (till exempel en Unicode-teckensträng) skickar marshallern anroparen en direktpekare till hanterade strängar i den interna Unicode-bufferten i stället för att kopiera den till en ny buffert.

Varning

När en sträng skickas av ett värde får anroparen aldrig ändra referensen som skickas av marshallern. Om du gör det kan den hanterade heapen skadas.

När en System.String skickas med referens kopierar marshaller innehållet i strängen till en sekundär buffert innan anropet görs. Sedan kopieras innehållet i bufferten till en ny sträng vid retur från anropet. Den här tekniken säkerställer att den oföränderliga hanterade strängen förblir oförändrad.

När ett System.Text.StringBuilder värde skickas av skickar marshaller en referens till en tillfällig kopia av den interna bufferten för StringBuilder till anroparen. Anroparen och anroparen måste komma överens om buffertens storlek. Anroparen ansvarar för att skapa en StringBuilder med tillräcklig längd. Anropare måste vidta nödvändiga försiktighetsåtgärder för att säkerställa att bufferten inte överskrids. StringBuilder är ett undantag från regeln att referenstyper som skickas av värde skickas som parametrar som In standard. StringBuilder skickas alltid som In/Out.

Se även