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 out
nemref
) 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 LPWStr
a .
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ű nMaxCount
pufferre 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 StringBuilder
kapacitá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
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: