Sdílet prostřednictvím


Kopírování a přichycování

Při zařazování dat může zkopírovat nebo připnout data, která jsou zařazována. Kopírování dat umístí kopii dat z jednoho umístění paměti do jiného umístění paměti. Následující obrázek ukazuje rozdíly mezi kopírováním typu hodnoty a kopírováním typu předaného odkazem ze spravované do nespravované paměti.

Diagram that shows how value and reference types are copied.

Argumenty metody předané hodnotou jsou zařazovány do nespravovaného kódu jako hodnoty v zásobníku. Proces kopírování je přímý. Argumenty předané odkazem se předávají jako ukazatele na zásobníku. Odkazové typy se předávají také podle hodnoty a odkazu. Jak ukazuje následující obrázek, odkazové typy předané podle hodnoty se zkopírují nebo připnou:

Diagram showing reference types passed by value and by reference.

Připnutí dočasně uzamkne data v aktuálním umístění paměti, takže je nebude možné přemístit uvolňováním paměti modulu CLR (Common Language Runtime). Marshaller připne data, aby se snížila režie při kopírování a zvýšil výkon. Typ dat určuje, zda se kopíruje nebo připne během procesu zařazování. Při připnutí se automaticky provádí při zařazování objektů, jako Stringje například , ale můžete také ručně připnout paměť pomocí GCHandle třídy.

Formátované třídy Blittable

Formátované blittable třídy mají pevné rozložení (formátované) a běžné znázornění dat v spravované i nespravované paměti. Pokud tyto typy vyžadují zařazování, předá se přímo volaný ukazatel na objekt v haldě. Volaný může změnit obsah umístění paměti, na které odkazuje ukazatel.

Poznámka:

Volaný může změnit obsah paměti, pokud je parametr označený jako Out nebo In/Out. Naproti tomu volaný by se měl vyhnout změně obsahu, když je parametr nastaven na zařazování jako In, což je výchozí hodnota pro formátované blittable typy. Úprava objektu In generuje problémy, když je stejná třída exportována do knihovny typů a používá se k volání mezi apartmány.

Formátované neschovatelné třídy

Formátované nesmazatelné třídy mají pevné rozložení (formátované), ale reprezentace dat se liší ve spravované a nespravované paměti. Data mohou vyžadovat transformaci za následujících podmínek:

  • Pokud je nebližovatelná třída zařazována podle hodnoty, volaný obdrží ukazatel na kopii datové struktury.

  • Pokud je nebližovatelná třída zařazována odkazem, volaný obdrží ukazatel na ukazatel na kopii datové struktury.

  • InAttribute Pokud je atribut nastaven, tato kopie je vždy inicializována se stavem instance, seřazovat podle potřeby.

  • OutAttribute Pokud je atribut nastaven, stav se vždy zkopíruje zpět do instance při vrácení, seřaďování podle potřeby.

  • Pokud jsou nastaveny inAttribute i OutAttribute, jsou vyžadovány obě kopie. Pokud některý z atributů vynecháte, může marshaller optimalizovat odstraněním obou kopií.

Typy odkazů

Odkazové typy mohou být předány podle hodnoty nebo odkazu. Při předání podle hodnoty se v zásobníku předá ukazatel na typ. Při předání odkazem se v zásobníku předá ukazatel na ukazatel na typ.

Odkazové typy mají následující podmíněné chování:

  • Pokud je typ odkazu předán hodnotou a má členy nelimitovatelných typů, jsou typy převedeny dvakrát:

    • Když se argument předá nespravované straně.

    • Při návratu z hovoru.

    Aby nedocházelo k zbytečnému kopírování a převodu, jsou tyto typy zařazovány jako v parametrech. Atributy InAttribute a OutAttribute musíte explicitně použít u argumentu volajícího, aby se zobrazily změny provedené volaným.

  • Pokud je typ odkazu předán podle hodnoty a má pouze členy blittable typů, lze ho připnout během zařazování a všechny změny členů typu volaným se zobrazí volajícím. Pokud chcete toto chování, použijte explicitně InAttribute a OutAttribute . Bez těchto směrových atributů neexportuje směrová informace do knihovny typů (exportuje se jako In, což je výchozí nastavení) a to může způsobit problémy s křížovým zařazováním mezi apartmány MODELU COM.

  • Pokud je typ odkazu předán odkazem, bude ve výchozím nastavení zařazován jako In/Out.

System.String a System.Text.StringBuilder

Pokud jsou data zařazována do nespravovaného kódu podle hodnoty nebo odkazu, marshaller obvykle kopíruje data do sekundární vyrovnávací paměti (pravděpodobně převod znakových sad během kopírování) a předá odkaz na vyrovnávací paměť volaného. Pokud není odkaz přidělený nástrojem SysAllocString, je odkaz vždy přidělen pomocí coTaskMemAlloc.

Při optimalizaci, pokud je hodnota String nebo StringBuilder je zařazována podle hodnoty (například řetězec znaků Unicode), marshaller předá volaný přímý ukazatel na spravované řetězce v interní vyrovnávací paměti Unicode místo toho, aby ho nekopíroval do nové vyrovnávací paměti.

Upozornění

Pokud je řetězec předán hodnotou, volaný nesmí nikdy změnit odkaz předaný marshallerem. To může poškodit spravovanou haldu.

System.String Při předání odkazu, marshaller zkopíruje obsah řetězce do sekundární vyrovnávací paměti před voláním. Potom zkopíruje obsah vyrovnávací paměti do nového řetězce při návratu z volání. Tato technika zajišťuje, že neměnný spravovaný řetězec zůstane nezměněný.

System.Text.StringBuilder Když je předána hodnotou, marshaller předá odkaz na dočasnou kopii interní vyrovnávací paměti StringBuilder volajícímu. Volající a volaný musí souhlasit s velikostí vyrovnávací paměti. Volající zodpovídá za vytvoření stringBuilderu odpovídající délky. Volaný musí provést nezbytná opatření, aby se zajistilo, že se vyrovnávací paměť nepřeteče. StringBuilder je výjimka pravidla, které odkazuje na typy předané hodnotou jsou ve výchozím nastavení předány jako In parametry. StringBuilder je vždy předán jako In/Out.

Viz také