Kopiëren en vastmaken
Bij het marshallen van gegevens kan de interop marshaller de gegevens kopiëren of vastmaken die worden ge marshalld. Als u de gegevens kopieert, wordt een kopie van gegevens van de ene geheugenlocatie op een andere geheugenlocatie opgeslagen. In de volgende afbeelding ziet u de verschillen tussen het kopiëren van een waardetype en het kopiëren van een type dat wordt doorgegeven door verwijzing van beheerd naar onbeheerd geheugen.
Methodeargumenten die door de waarde worden doorgegeven, worden ge marshalld naar onbeheerde code als waarden op de stack. Het kopieerproces is direct. Argumenten die door verwijzing worden doorgegeven, worden doorgegeven als aanwijzers op de stack. Verwijzingstypen worden ook doorgegeven door waarde en verwijzing. Zoals in de volgende afbeelding wordt weergegeven, worden verwijzingstypen die door de waarde worden doorgegeven, gekopieerd of vastgemaakt:
Door het vastmaken worden de gegevens tijdelijk vergrendeld op de huidige geheugenlocatie, zodat deze niet kunnen worden verplaatst door de garbagecollector van de algemene taalruntime. De marshaller maakt gegevens vast om de overhead van het kopiëren en verbeteren van de prestaties te verminderen. Het type gegevens bepaalt of deze tijdens het marshallproces worden gekopieerd of vastgemaakt. Vastmaken wordt automatisch uitgevoerd tijdens het marshallen voor objecten zoals String, maar u kunt ook handmatig geheugen vastmaken met behulp van de GCHandle klasse.
Opgemaakte Blittable-klassen
Opgemaakte blittable-klassen hebben een vaste indeling (opgemaakt) en algemene gegevensweergave in zowel beheerd als onbeheerd geheugen. Wanneer deze typen marshalling vereisen, wordt een aanwijzer naar het object in de heap rechtstreeks doorgegeven aan de aanwijzer. De aanwijzer kan de inhoud van de geheugenlocatie waarnaar wordt verwezen door de aanwijzer wijzigen.
Notitie
De aanwijzer kan de geheugeninhoud wijzigen als de parameter is gemarkeerd als Out of In/Out. De aangeroepen gebruiker moet daarentegen voorkomen dat de inhoud wordt gewijzigd wanneer de parameter is ingesteld op marshal als In, wat de standaardinstelling is voor opgemaakte blittable-typen. Als u een In-object wijzigt, worden er problemen gegenereerd wanneer dezelfde klasse wordt geëxporteerd naar een typebibliotheek en wordt gebruikt voor het aanroepen van meerdere appartementen.
Niet-belichte klassen opgemaakt
Opgemaakte niet-belichte klassen hebben een vaste indeling (opgemaakt), maar de gegevensweergave verschilt in beheerd en onbeheerd geheugen. De gegevens kunnen transformatie vereisen onder de volgende voorwaarden:
Als een niet-belichte klasse op waarde wordt ingedeeld, ontvangt de aanwijzer een aanwijzer naar een kopie van de gegevensstructuur.
Als een niet-belichte klasse op basis van verwijzing wordt aangeduid, ontvangt de aanwijzer een aanwijzer naar een kopie van de gegevensstructuur.
Als het InAttribute kenmerk is ingesteld, wordt deze kopie altijd geïnitialiseerd met de status van het exemplaar, indien nodig marshalling.
Als het OutAttribute kenmerk is ingesteld, wordt de status zo nodig altijd terug gekopieerd naar het exemplaar dat wordt geretourneerd.
Als zowel InAttribute als OutAttributezijn ingesteld, zijn beide kopieën vereist. Als een van beide kenmerken wordt weggelaten, kan de marshaller optimaliseren door een van beide kopieën te elimineren.
Verwijzingstypen
Verwijzingstypen kunnen worden doorgegeven op waarde of naslaginformatie. Wanneer ze door een waarde worden doorgegeven, wordt een aanwijzer naar het type doorgegeven aan de stack. Wanneer een verwijzing wordt doorgegeven, wordt een aanwijzer naar een aanwijzer doorgegeven aan het type op de stack.
Referentietypen hebben het volgende voorwaardelijke gedrag:
Als een verwijzingstype wordt doorgegeven door een waarde en lid is van niet-belichte typen, worden de typen tweemaal geconverteerd:
Wanneer een argument wordt doorgegeven aan de onbeheerde zijde.
Bij terugkomst van het gesprek.
Om onnodig kopiëren en converteren te voorkomen, worden deze typen ge marshalld als In parameters. U moet expliciet de kenmerken InAttribute en OutAttribute toepassen op een argument voor de aanroeper om wijzigingen te zien die door de aanroeper zijn aangebracht.
Als een verwijzingstype wordt doorgegeven door een waarde en alleen leden van belichte typen heeft, kan het worden vastgemaakt tijdens marshalling en eventuele wijzigingen die zijn aangebracht aan de leden van het type door de gebruiker worden gezien door de beller. Pas InAttribute en OutAttribute expliciet toe als u dit gedrag wilt. Zonder deze directionele kenmerken exporteert de interop marshaller geen directionele informatie naar de typebibliotheek (het exporteert als In, dit is de standaardinstelling) en dit kan problemen veroorzaken met com cross-apartment marshalling.
Als een verwijzingstype wordt doorgegeven via een verwijzing, wordt dit standaard als In/Out-adres weergegeven.
System.String en System.Text.StringBuilder
Wanneer gegevens worden ge marshalleerd naar onbeheerde code op waarde of verwijzing, kopieert de marshaller de gegevens doorgaans naar een secundaire buffer (mogelijk het converteren van tekensets tijdens de kopie) en geeft een verwijzing naar de buffer door aan de aanwijzer. Tenzij de verwijzing een BSTR is die is toegewezen met SysAllocString, wordt de verwijzing altijd toegewezen aan CoTaskMemAlloc.
Als optimalisatie wanneer een waarde ( String zoals een Unicode-tekenreeks) wordt gebruikt, StringBuilder geeft de marshaller een directe aanwijzer door aan beheerde tekenreeksen in de interne Unicode-buffer in plaats van deze naar een nieuwe buffer te kopiëren.
Let op
Wanneer een tekenreeks wordt doorgegeven door een waarde, mag de aanwijzer nooit de verwijzing wijzigen die door de marshaller is doorgegeven. Hierdoor kan de beheerde heap beschadigd raken.
Wanneer een System.String verwijzing wordt doorgegeven, kopieert de marshaller de inhoud van de tekenreeks naar een secundaire buffer voordat de aanroep wordt uitgevoerd. Vervolgens wordt de inhoud van de buffer gekopieerd naar een nieuwe tekenreeks bij terugkeer vanuit de aanroep. Deze techniek zorgt ervoor dat de onveranderbare beheerde tekenreeks ongewijzigd blijft.
Wanneer een System.Text.StringBuilder waarde wordt doorgegeven, geeft de marshaller een verwijzing door naar een tijdelijke kopie van de interne buffer van de StringBuilder aan de aanroeper . De beller en de beller moeten akkoord gaan met de grootte van de buffer. De aanroeper is verantwoordelijk voor het maken van een StringBuilder van voldoende lengte. De aangeroepene moet de nodige voorzorgsmaatregelen nemen om ervoor te zorgen dat de buffer niet wordt overschreden. StringBuilder is een uitzondering op de regel die verwijzingstypen die door de waarde worden doorgegeven, worden standaard doorgegeven als In
parameters. StringBuilder
wordt altijd doorgegeven als In
/Out
.