Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Zowel de System.String-klasse als de System.Text.StringBuilder-klasse hebben vergelijkbaar marshallinggedrag.
Tekenreeksen worden aangeduid als een COM-stijltype BSTR of als een tekenreeks met null-einden (een tekenmatrix die eindigt op een null-teken). De tekens in de tekenreeks kunnen worden gemarshalled als Unicode (de standaardinstelling op Windows-systemen) of ANSI.
Tekenreeksen die worden gebruikt in interfaces
In de volgende tabel ziet u de marshallopties voor het gegevenstype tekenreeks wanneer marshalling wordt gebruikt als een methodeargument voor onbeheerde code. Het MarshalAsAttribute kenmerk biedt verschillende UnmanagedType opsommingswaarden voor het marshallen van strings naar COM-interfaces.
| Opsommingstype | Beschrijving van niet-beheerde indeling | 
|---|---|
              UnmanagedType.BStr (standaard) | 
Een COM-stijl BSTR met een voorvoegsellengte en Unicode-tekens. | 
UnmanagedType.LPStr | 
Een aanwijzer naar een null-beëindigde matrix met ANSI-tekens. | 
UnmanagedType.LPWStr | 
Een aanwijzer naar een null-beëindigde matrix met Unicode-tekens. | 
Deze tabel is van toepassing op String. Voor StringBuilder, de enige opties toegestaan zijn UnmanagedType.LPStr en UnmanagedType.LPWStr.
In het volgende voorbeeld ziet u tekenreeksen die zijn gedeclareerd in de IStringWorker interface.
public interface IStringWorker
{
    void PassString1(string s);
    void PassString2([MarshalAs(UnmanagedType.BStr)] string s);
    void PassString3([MarshalAs(UnmanagedType.LPStr)] string s);
    void PassString4([MarshalAs(UnmanagedType.LPWStr)] string s);
    void PassStringRef1(ref string s);
    void PassStringRef2([MarshalAs(UnmanagedType.BStr)] ref string s);
    void PassStringRef3([MarshalAs(UnmanagedType.LPStr)] ref string s);
    void PassStringRef4([MarshalAs(UnmanagedType.LPWStr)] ref string s);
}
Public Interface IStringWorker
    Sub PassString1(s As String)
    Sub PassString2(<MarshalAs(UnmanagedType.BStr)> s As String)
    Sub PassString3(<MarshalAs(UnmanagedType.LPStr)> s As String)
    Sub PassString4(<MarshalAs(UnmanagedType.LPWStr)> s As String)
    Sub PassStringRef1(ByRef s As String)
    Sub PassStringRef2(<MarshalAs(UnmanagedType.BStr)> ByRef s As String)
    Sub PassStringRef3(<MarshalAs(UnmanagedType.LPStr)> ByRef s As String)
    Sub PassStringRef4(<MarshalAs(UnmanagedType.LPWStr)> ByRef s As String)
End Interface
In het volgende voorbeeld ziet u de bijbehorende interface die wordt beschreven in een typebibliotheek.
interface IStringWorker : IDispatch
{
    HRESULT PassString1([in] BSTR s);
    HRESULT PassString2([in] BSTR s);
    HRESULT PassString3([in] LPStr s);
    HRESULT PassString4([in] LPWStr s);
    HRESULT PassStringRef1([in, out] BSTR *s);
    HRESULT PassStringRef2([in, out] BSTR *s);
    HRESULT PassStringRef3([in, out] LPStr *s);
    HRESULT PassStringRef4([in, out] LPWStr *s);
};
Tekenreeksen die worden gebruikt bij het aanroepen van platformfuncties
Wanneer de CharSet Unicode is of een tekenreeksargument expliciet is gemarkeerd als [MarshalAs(UnmanagedType.LPWSTR)] en de tekenreeks wordt doorgegeven door waarde (niet ref of out), wordt de tekenreeks vastgemaakt en rechtstreeks door systeemeigen code gebruikt. Anders roept het platform tekenreeksargumenten aan, die worden geconverteerd van de .NET Framework-indeling (Unicode) naar de niet-beheerde platformindeling. Tekenreeksen zijn onveranderbaar en worden niet van onbeheerd geheugen naar beheerd geheugen gekopieerd wanneer de aanroep terugkeert.
Native code is alleen verantwoordelijk voor het vrijgeven van het geheugen wanneer de tekenreeks door verwijzing wordt doorgegeven en er een nieuwe waarde aan wordt toegewezen. Anders is de .NET-runtime eigenaar van het geheugen en wordt deze na de aanroep vrijgegeven.
De volgende tabel bevat de marshallingopties voor tekenreeksen wanneer ze worden doorgegeven als methodeargument bij een platformaanroep. Het MarshalAsAttribute kenmerk biedt verschillende UnmanagedType opsommingswaarden voor marshal strings.
| Opsommingstype | Beschrijving van niet-beheerde indeling | 
|---|---|
UnmanagedType.AnsiBStr | 
Een COM-stijl BSTR met een voorvoegsellengte en ANSI-tekens. | 
UnmanagedType.BStr | 
Een COM-stijl BSTR met een voorvoegsellengte en Unicode-tekens. | 
              UnmanagedType.LPStr (standaard) | 
Een aanwijzer naar een null-beëindigde matrix met ANSI-tekens. | 
UnmanagedType.LPTStr | 
Een aanwijzer naar een door null beëindigde matrix met platformafhankelijke tekens. | 
UnmanagedType.LPUTF8Str | 
Een aanwijzer naar een door null beëindigde matrix met met UTF-8 gecodeerde tekens. | 
UnmanagedType.LPWStr | 
Een aanwijzer naar een null-beëindigde matrix met Unicode-tekens. | 
UnmanagedType.TBStr | 
Een COM-stijl BSTR met een voorvoegsellengte en platformafhankelijke tekens. | 
VBByRefStr | 
Een waarde waarmee Visual Basic een tekenreeks in niet-beheerde code kan wijzigen en de resultaten in beheerde code laat zien. Deze waarde wordt alleen ondersteund voor het aanroepen van het platform. Dit is de standaardwaarde in Visual Basic voor ByVal tekenreeksen. | 
Deze tabel is van toepassing op String. Voor StringBuilder, de enige opties zijn , LPStren LPTStrLPWStr.
In de volgende typedefinitie ziet u het juiste gebruik van MarshalAsAttribute voor het aanroepen van platformen.
class StringLibAPI
{
    [DllImport("StringLib.dll")]
    public static extern void PassLPStr([MarshalAs(UnmanagedType.LPStr)] string s);
    [DllImport("StringLib.dll")]
    public static extern void PassLPWStr([MarshalAs(UnmanagedType.LPWStr)] string s);
    [DllImport("StringLib.dll")]
    public static extern void PassLPTStr([MarshalAs(UnmanagedType.LPTStr)] string s);
    [DllImport("StringLib.dll")]
    public static extern void PassLPUTF8Str([MarshalAs(UnmanagedType.LPUTF8Str)] string s);
    [DllImport("StringLib.dll")]
    public static extern void PassBStr([MarshalAs(UnmanagedType.BStr)] string s);
    [DllImport("StringLib.dll")]
    public static extern void PassAnsiBStr([MarshalAs(UnmanagedType.AnsiBStr)] string s);
    [DllImport("StringLib.dll")]
    public static extern void PassTBStr([MarshalAs(UnmanagedType.TBStr)] string s);
}
Class StringLibAPI
    Public Declare Auto Sub PassLPStr Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.LPStr)> s As String)
    Public Declare Auto Sub PassLPWStr Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.LPWStr)> s As String)
    Public Declare Auto Sub PassLPTStr Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.LPTStr)> s As String)
    Public Declare Auto Sub PassLPUTF8Str Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.LPUTF8Str)> s As String)
    Public Declare Auto Sub PassBStr Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.BStr)> s As String)
    Public Declare Auto Sub PassAnsiBStr Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.AnsiBStr)> s As String)
    Public Declare Auto Sub PassTBStr Lib "StringLib.dll" (
        <MarshalAs(UnmanagedType.TBStr)> s As String)
End Class
Tekenreeksen die worden gebruikt in structuren
Tekenreeksen zijn geldige leden van structuren; StringBuilder buffers zijn echter ongeldig in structuren. In de volgende tabel ziet u de marshallingsopties voor het String gegevenstype wanneer het type als veld wordt gemarshalled. Het MarshalAsAttribute kenmerk biedt verschillende UnmanagedType opsommingswaarden om strings naar een veld te converteren.
| Opsommingstype | Beschrijving van niet-beheerde indeling | 
|---|---|
UnmanagedType.BStr | 
Een COM-stijl BSTR met een voorvoegsellengte en Unicode-tekens. | 
              UnmanagedType.LPStr (standaard) | 
Een aanwijzer naar een null-beëindigde matrix met ANSI-tekens. | 
UnmanagedType.LPTStr | 
Een aanwijzer naar een door null beëindigde matrix met platformafhankelijke tekens. | 
UnmanagedType.LPUTF8Str | 
Een aanwijzer naar een door null beëindigde matrix met met UTF-8 gecodeerde tekens. | 
UnmanagedType.LPWStr | 
Een aanwijzer naar een null-beëindigde matrix met Unicode-tekens. | 
UnmanagedType.ByValTStr | 
Een matrix met vaste lengte van tekens; het type van de matrix wordt bepaald door de tekenset van de structuur die de matrix bevat. | 
Het ByValTStr type wordt gebruikt voor inline tekenmatrices met een vaste lengte die in een structuur worden weergegeven. Andere typen zijn van toepassing op tekenreeksverwijzingen in structuren die verwijzingen naar tekenreeksen bevatten.
Het CharSet argument van de StructLayoutAttribute, dat wordt toegepast op de omliggende structuur, bepaalt de tekenopmaak van tekenreeksen in structuren. De volgende voorbeeldstructuren bevatten tekenreeksverwijzingen en inlinetekenreeksen, evenals ANSI-, Unicode- en platformafhankelijke tekens. De weergave van deze structuren in een typebibliotheek wordt weergegeven in de volgende C++-code:
struct StringInfoA
{
    char *  f1;
    char    f2[256];
};
struct StringInfoW
{
    WCHAR * f1;
    WCHAR   f2[256];
    BSTR    f3;
};
struct StringInfoT
{
    TCHAR * f1;
    TCHAR   f2[256];
};
In het volgende voorbeeld ziet u hoe u de MarshalAsAttribute structuur in verschillende formaten kunt definiëren.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct StringInfoA
{
    [MarshalAs(UnmanagedType.LPStr)] public string f1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string f2;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct StringInfoW
{
    [MarshalAs(UnmanagedType.LPWStr)] public string f1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string f2;
    [MarshalAs(UnmanagedType.BStr)] public string f3;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct StringInfoT
{
    [MarshalAs(UnmanagedType.LPTStr)] public string f1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string f2;
}
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Ansi)> _
Structure StringInfoA
    <MarshalAs(UnmanagedType.LPStr)> Public f1 As String
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
    Public f2 As String
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Unicode)> _
Structure StringInfoW
    <MarshalAs(UnmanagedType.LPWStr)> Public f1 As String
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
    Public f2 As String
<MarshalAs(UnmanagedType.BStr)> Public f3 As String
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Auto)> _
Structure StringInfoT
    <MarshalAs(UnmanagedType.LPTStr)> Public f1 As String
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
    Public f2 As String
End Structure
Tekenreeksbuffers met vaste lengte
In sommige gevallen moet een tekenbuffer met een vaste lengte worden doorgegeven aan onbeheerde code die moet worden gemanipuleerd. Het doorgeven van een tekenreeks werkt in dit geval niet omdat de gebruiker de inhoud van de doorgegeven buffer niet kan wijzigen. Zelfs als de tekenreeks wordt doorgegeven via verwijzing, is er geen manier om de buffer te initialiseren naar een bepaalde grootte.
De oplossing is het doorgeven van een byte[] of char[], afhankelijk van de verwachte codering, als het argument in plaats van een String. Het array, indien gemarkeerd met [Out], kan worden gedereferentieerd en gewijzigd door de aangeroepen functie, mits de wijzigingen niet groter zijn dan de capaciteit van het toegewezen array.
De Windows GetWindowText API-functie (gedefinieerd in winuser.h) vereist bijvoorbeeld dat de aanroeper een tekenbuffer met een vaste lengte doorgeeft waaraan de functie de tekst van het venster schrijft. Het lpString argument verwijst naar een aanroeper toegewezen buffer van grootte nMaxCount. De aanroeper wordt verwacht de buffer toe te wijzen en het nMaxCount argument in te stellen op de grootte van de toegewezen buffer. In het volgende voorbeeld ziet u de GetWindowText functiedeclaratie zoals gedefinieerd in winuser.h.
int GetWindowText(
    HWND hWnd,        // Handle to window or control.
    LPTStr lpString,  // Text buffer.
    int nMaxCount     // Maximum number of characters to copy.
);
Een char[] kan worden gerefereerd en gewijzigd door de aanroeper. Het volgende codevoorbeeld toont aan hoe ArrayPool<char> kan worden gebruikt om een char[] vooraf toe te wijzen.
using System;
using System.Buffers;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
    [DllImport("User32.dll", CharSet = CharSet.Unicode)]
    public static extern void GetWindowText(IntPtr hWnd, [Out] char[] lpString, int nMaxCount);
}
public class Window
{
    internal IntPtr h;        // Internal handle to Window.
    public string GetText()
    {
        char[] buffer = ArrayPool<char>.Shared.Rent(256 + 1);
        NativeMethods.GetWindowText(h, buffer, buffer.Length);
        return new string(buffer);
    }
}
Imports System
Imports System.Buffers
Imports System.Runtime.InteropServices
Friend Class NativeMethods
    Public Declare Auto Sub GetWindowText Lib "User32.dll" _
        (hWnd As IntPtr, <Out> lpString() As Char, nMaxCount As Integer)
End Class
Public Class Window
    Friend h As IntPtr ' Friend handle to Window.
    Public Function GetText() As String
        Dim buffer() As Char = ArrayPool(Of Char).Shared.Rent(256 + 1)
        NativeMethods.GetWindowText(h, buffer, buffer.Length)
        Return New String(buffer)
   End Function
End Class
Een andere oplossing is om een StringBuilder als argument door te geven in plaats van een String. De buffer die wordt gecreëerd bij het marshallen van een StringBuilder kan door de aangeroepene worden gedereferenced en gewijzigd, mits het niet de capaciteit van de StringBuilder overschrijdt. Het kan ook worden geïnitialiseerd tot een vaste lengte. Als u bijvoorbeeld een StringBuilder buffer initialiseert met een capaciteit van N, biedt de marshaller een buffer met een grootte van (N+1) tekens. De +1 houdt rekening met het feit dat de niet-beheerde tekenreeks een null-eindteken heeft, terwijl StringBuilder dat niet het geval is.
Opmerking
Over het algemeen wordt het doorgeven StringBuilder van argumenten niet aanbevolen als u zich zorgen maakt over prestaties. Zie Tekenreeksparameters voor meer informatie.