Megosztás a következőn keresztül:


Sztringek alapértelmezett rendezése

Az osztályok és System.Text.StringBuilder az System.String osztályok is hasonló rendezési viselkedést használnak.

A sztringek COM-stílusú BSTR típusként vagy null értékű karakterláncként vannak rendezve (null karakterrel végződő karaktertömb). A sztringen belüli karakterek Unicode -ként (windowsos rendszereken alapértelmezett) vagy ANSI-ként rendezhetők.

Interfészekben használt sztringek

Az alábbi táblázat a sztring adattípusának rendezési beállításait mutatja be, ha metódusargumentumként rendezve van a nem felügyelt kódhoz. Az MarshalAsAttribute attribútum számos UnmanagedType enumerálási értéket biztosít a COM-felületekhez való marshal sztringekhez.

Számbavétel típusa A nem felügyelt formátum leírása
UnmanagedType.BStr (alapértelmezett) COM-stílusú BSTR , előtaggal ellátott hosszúságú és Unicode-karakterekkel.
UnmanagedType.LPStr Egy ANSI-karakterekből álló null értékű tömbre mutató mutató.
UnmanagedType.LPWStr Unicode-karakterek null értékű tömbjének mutatója.

Ez a tábla a következőkre Stringvonatkozik: . Ebben StringBuilderaz esetben csak a következő lehetőségek engedélyezettek UnmanagedType.LPStr : és UnmanagedType.LPWStr.

Az alábbi példa a IStringWorker felületen deklarált sztringeket mutatja be.

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

Az alábbi példa egy típustárban leírt megfelelő felületet mutatja be.

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);
};

A platformhívásban használt sztringek

Ha a CharSet Unicode, vagy egy karakterlánc-argumentum explicit módon [MarshalAs(UnmanagedType.LPWSTR)] néven van megjelölve, és a sztringet érték (nem vagy outnemref) adja át, a sztring rögzítve lesz, és közvetlenül a natív kód használja. Ellenkező esetben a platform meghívja a sztringargumentumokat, és a .NET-keretrendszer formátumból (Unicode) nem felügyelt formátumba konvertálja a platformot. A sztringek nem módosíthatók, és nem lesznek visszamásolva a nem felügyelt memóriából a felügyelt memóriába a hívás visszatérésekor.

A natív kód csak akkor adja ki a memóriát, ha a sztringet hivatkozással adja át, és új értéket rendel hozzá. Ellenkező esetben a .NET-futtatókörnyezet a memória tulajdonosa, és a hívás után felszabadítja azt.

Az alábbi táblázat a sztringek rendezési beállításait sorolja fel, amikor egy platformhívás metódusargumentumaként vannak rendezve. Az MarshalAsAttribute attribútum számos UnmanagedType enumerálási értéket biztosít a marshal sztringekhez.

Számbavétel típusa A nem felügyelt formátum leírása
UnmanagedType.AnsiBStr COM-stílus BSTR előtaggal és ANSI-karakterekkel.
UnmanagedType.BStr COM-stílusú BSTR , előtaggal ellátott hosszúságú és Unicode-karakterekkel.
UnmanagedType.LPStr (alapértelmezett) Egy ANSI-karakterekből álló null értékű tömbre mutató mutató.
UnmanagedType.LPTStr A platformfüggetlen karakterek null értékű tömbjének mutatója.
UnmanagedType.LPUTF8Str Mutató az UTF-8 kódolt karakterek null értékű tömbje felé.
UnmanagedType.LPWStr Unicode-karakterek null értékű tömbjének mutatója.
UnmanagedType.TBStr COM-stílus BSTR előtaggal és platformfüggetlen karakterekkel.
VBByRefStr Olyan érték, amely lehetővé teszi, hogy a Visual Basic módosítson egy sztringet nem felügyelt kódban, és hogy az eredmények megjelenjenek a felügyelt kódban. Ez az érték csak platformhívás esetén támogatott. Ez az alapértelmezett érték a Visual Basicben a ByVal sztringekhez.

Ez a tábla a következőkre Stringvonatkozik: . Ebben StringBuilderaz esetben az egyetlen lehetőség az LPStr, LPTStrés LPWStra .

Az alábbi típusdefiníció a platformhívási MarshalAsAttribute hívások helyes használatát mutatja.

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

Struktúrákban használt sztringek

A sztringek a struktúrák érvényes tagjai; a StringBuilder pufferek azonban érvénytelenek a struktúrákban. Az alábbi táblázat az adattípus rendezési beállításait String mutatja be, ha a típus mezőként van rendezve. Az MarshalAsAttribute attribútum számos UnmanagedType enumerálási értéket biztosít egy mező marshal sztringjeihez.

Számbavétel típusa A nem felügyelt formátum leírása
UnmanagedType.BStr COM-stílusú BSTR , előtaggal ellátott hosszúságú és Unicode-karakterekkel.
UnmanagedType.LPStr (alapértelmezett) Egy ANSI-karakterekből álló null értékű tömbre mutató mutató.
UnmanagedType.LPTStr A platformfüggetlen karakterek null értékű tömbjének mutatója.
UnmanagedType.LPUTF8Str Mutató az UTF-8 kódolt karakterek null értékű tömbje felé.
UnmanagedType.LPWStr Unicode-karakterek null értékű tömbjének mutatója.
UnmanagedType.ByValTStr Rögzített hosszúságú karaktertömb; a tömb típusát az azt tartalmazó struktúra karakterkészlete határozza meg.

A ByValTStr típus beágyazott, rögzített hosszúságú karaktertömbökhöz használatos, amelyek egy struktúrában jelennek meg. Más típusok a sztringekre mutató mutatókat tartalmazó struktúrákban található sztringhivatkozásokra vonatkoznak.

A CharSet szerkezetre alkalmazott argumentum StructLayoutAttribute határozza meg a struktúrák sztringjeinek karakterformátumát. Az alábbi példastruktúrák sztringhivatkozásokat és beágyazott sztringeket, valamint ANSI-, Unicode- és platformfüggő karaktereket tartalmaznak. Ezeknek a struktúráknak a típustárban való ábrázolása a következő C++ kódban jelenik meg:

struct StringInfoA
{
    char *  f1;
    char    f2[256];
};

struct StringInfoW
{
    WCHAR * f1;
    WCHAR   f2[256];
    BSTR    f3;
};

struct StringInfoT
{
    TCHAR * f1;
    TCHAR   f2[256];
};

Az alábbi példa bemutatja, hogyan definiálhatja ugyanazt a MarshalAsAttribute struktúrát különböző formátumokban.

[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

Rögzített hosszúságú sztringpufferek

Bizonyos körülmények között a rögzített hosszúságú karakterpuffert nem felügyelt kódba kell továbbítani a manipuláláshoz. A sztringek egyszerű átadása ebben az esetben nem működik, mert a hívó nem tudja módosítani az átadott puffer tartalmát. Még akkor sem inicializálhatja a puffert egy adott méretre, ha a sztringet hivatkozással továbbítja.

A megoldás az, hogy a várt kódolástól függően egy vagy char[]– a várt kódolástól függően – argumentumot ad át byte[] ahelyett, hogy egy String. A tömb, ha megjelölve [Out]van, a hívó elhalaszthatja és módosíthatja, feltéve, hogy az nem haladja meg a lefoglalt tömb kapacitását.

A (winuser.h nyelven definiált) Windows GetWindowText API-függvény például megköveteli, hogy a hívó egy rögzített hosszúságú karakterpuffert adjon át, amelybe a függvény az ablak szövegét írja. Az lpString argumentum egy hívó által lefoglalt méretű nMaxCountpufferre mutat. A hívó várhatóan lefoglalja a puffert, és az nMaxCount argumentumot a lefoglalt puffer méretére állítja. Az alábbi példa a GetWindowText winuser.h fájlban definiált függvénydeklarációt mutatja be.

int GetWindowText(
    HWND hWnd,        // Handle to window or control.
    LPTStr lpString,  // Text buffer.
    int nMaxCount     // Maximum number of characters to copy.
);

Az A-t char[] a hívó elhalaszthatja és módosíthatja. Az alábbi példakód bemutatja, hogyan ArrayPool<char> lehet előre lefoglalni egy char[].

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

Egy másik megoldás az, hogy egy argumentumot ad át StringBuilder ahelyett, hogy egy String. A rendszerezéskor StringBuilder létrehozott puffert a hívó késleltetheti és módosíthatja, feltéve, hogy az nem haladja meg a StringBuilderkapacitását. Rögzített hosszúságúra is inicializálható. Ha például inicializál egy StringBuilder puffert egy kapacitásba N, a rendező egy (N+1) karakter hosszúságú puffert biztosít. A +1 azt a tényt adja meg, hogy a nem felügyelt sztring null terminátort tartalmaz, miközben StringBuilder nem.

Feljegyzés

Az argumentumok átadása StringBuilder általában nem ajánlott, ha a teljesítmény miatt aggódik. További információ: Sztringparaméterek.

Lásd még