Dizeler için varsayılan sıralama
System.String Hem hem de System.Text.StringBuilder sınıfları benzer bir sıralama davranışına sahiptir.
Dizeler, COM stili BSTR
bir tür olarak veya null ile sonlandırılan bir dize (null karakterle biten bir karakter dizisi) olarak sıralanır. Dizedeki karakterler Unicode (Windows sistemlerinde varsayılan) veya ANSI olarak sıralanabilir.
Arabirimlerde kullanılan dizeler
Aşağıdaki tabloda, yönetilmeyen koda yöntem bağımsız değişkeni olarak sıralandığında dize veri türü için sıralama seçenekleri gösterilmektedir. özniteliği, MarshalAsAttribute dizeleri COM arabirimlerine sıralamak için birkaç UnmanagedType numaralandırma değeri sağlar.
Numaralandırma türü | Yönetilmeyen biçimin açıklaması |
---|---|
UnmanagedType.BStr (varsayılan) |
Ön ekli uzunluğu ve Unicode karakterleri olan COM stili BSTR . |
UnmanagedType.LPStr |
Null olarak sonlandırılan ANSI karakter dizisine yönelik bir işaretçi. |
UnmanagedType.LPWStr |
Null olarak sonlandırılan Unicode karakter dizisinin işaretçisi. |
Bu tablo için Stringgeçerlidir. için StringBuilder, yalnızca ve seçeneklerine UnmanagedType.LPStr
izin verilir UnmanagedType.LPWStr
.
Aşağıdaki örnek, arabirimde IStringWorker
bildirilen dizeleri gösterir.
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
Aşağıdaki örnek, bir tür kitaplığında açıklanan ilgili arabirimi gösterir.
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);
};
Platform çağırmada kullanılan dizeler
CharSet Unicode olduğunda veya dize bağımsız değişkeni açıkça [MarshalAs(UnmanagedType.LPWSTR)] olarak işaretlendiğinde ve dize değerle (veya out
değilref
) geçirildiğinde, dize sabitlenir ve doğrudan yerel kod tarafından kullanılır. Aksi takdirde platform çağrısı dize bağımsız değişkenlerini kopyalar ve .NET Framework biçiminden (Unicode) platform yönetilmeyen biçimine dönüştürür. Dizeler sabittir ve çağrı döndürdüğünde yönetilmeyen bellekten yönetilen belleğe geri kopyalanmaz.
Yerel kod yalnızca dize başvuruyla geçirildiğinde ve yeni bir değer atadığında belleği serbest bırakmakla sorumludur. Aksi takdirde, belleğe .NET çalışma zamanı sahip olur ve çağrıdan sonra serbest bırakır.
Aşağıdaki tabloda, bir platform çağırma çağrısının yöntem bağımsız değişkeni olarak sıralandığında dizeler için sıralama seçenekleri listelenmiştir. özniteliği, MarshalAsAttribute dizeleri sıralamak için birkaç UnmanagedType numaralandırma değeri sağlar.
Numaralandırma türü | Yönetilmeyen biçimin açıklaması |
---|---|
UnmanagedType.AnsiBStr |
Ön ekli uzunluğa ve ANSI karakterlerine sahip COM stili BSTR . |
UnmanagedType.BStr |
Ön ekli uzunluğu ve Unicode karakterleri olan COM stili BSTR . |
UnmanagedType.LPStr (varsayılan) |
Null olarak sonlandırılan ANSI karakter dizisine yönelik bir işaretçi. |
UnmanagedType.LPTStr |
Platforma bağımlı karakterlerin null olarak sonlandırılan dizisinin işaretçisi. |
UnmanagedType.LPUTF8Str |
NULL olarak sonlandırılan UTF-8 kodlanmış karakter dizisine işaretçi. |
UnmanagedType.LPWStr |
Null olarak sonlandırılan Unicode karakter dizisinin işaretçisi. |
UnmanagedType.TBStr |
Ön ekli uzunluğa ve platforma bağımlı karakterlere sahip COM stili BSTR . |
VBByRefStr |
Visual Basic'in yönetilmeyen koddaki bir dizeyi değiştirmesini ve sonuçların yönetilen koda yansıtılmalarını sağlayan değer. Bu değer yalnızca platform çağrısı için desteklenir. Bu, dizeler için ByVal Visual Basic'teki varsayılan değerdir. |
Bu tablo için Stringgeçerlidir. içinStringBuilder, yalnızca , LPTStr
ve seçeneklerine izin verilirLPStr
LPWStr
.
Aşağıdaki tür tanımı, platform çağırma çağrıları MarshalAsAttribute
için doğru kullanımını gösterir.
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
Yapılarda kullanılan dizeler
Dizeler yapıların geçerli üyeleridir; ancak, StringBuilder arabellekler yapılarda geçersizdir. Aşağıdaki tabloda, tür alan olarak sıralandığında veri türü için String sıralama seçenekleri gösterilmektedir. özniteliği, MarshalAsAttribute dizeleri bir alana sıralamak için birkaç UnmanagedType numaralandırma değeri sağlar.
Numaralandırma türü | Yönetilmeyen biçimin açıklaması |
---|---|
UnmanagedType.BStr |
Ön ekli uzunluğu ve Unicode karakterleri olan COM stili BSTR . |
UnmanagedType.LPStr (varsayılan) |
Null olarak sonlandırılan ANSI karakter dizisine yönelik bir işaretçi. |
UnmanagedType.LPTStr |
Platforma bağımlı karakterlerin null olarak sonlandırılan dizisinin işaretçisi. |
UnmanagedType.LPUTF8Str |
NULL olarak sonlandırılan UTF-8 kodlanmış karakter dizisine işaretçi. |
UnmanagedType.LPWStr |
Null olarak sonlandırılan Unicode karakter dizisinin işaretçisi. |
UnmanagedType.ByValTStr |
Sabit uzunlukta bir karakter dizisi; dizinin türü, içeren yapının karakter kümesi tarafından belirlenir. |
Türü ByValTStr
, bir yapı içinde görünen satır içi, sabit uzunlukta karakter dizileri için kullanılır. Diğer türler, dize işaretçileri içeren yapıların içinde yer alan dize başvurularına uygulanır.
İçeren CharSet
yapıya uygulanan öğesinin bağımsız değişkeni StructLayoutAttribute , yapılardaki dizelerin karakter biçimini belirler. Aşağıdaki örnek yapılar dize başvuruları ve satır içi dizelerin yanı sıra ANSI, Unicode ve platforma bağımlı karakterler içerir. Bu yapıların tür kitaplığındaki gösterimi aşağıdaki C++ kodunda gösterilir:
struct StringInfoA
{
char * f1;
char f2[256];
};
struct StringInfoW
{
WCHAR * f1;
WCHAR f2[256];
BSTR f3;
};
struct StringInfoT
{
TCHAR * f1;
TCHAR f2[256];
};
Aşağıdaki örnekte, aynı yapıyı farklı biçimlerde tanımlamak için öğesinin nasıl kullanılacağı MarshalAsAttribute gösterilmektedir.
[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
Sabit uzunlukta dize arabellekleri
Bazı durumlarda, yönetilmeyen koda işlenmek üzere sabit uzunlukta bir karakter arabelleği geçirilmelidir. Çağıran geçirilen arabelleğin içeriğini değiştiremediğinden bu durumda yalnızca bir dize geçirme işlemi çalışmaz. Dize başvuruyla geçirilse bile, arabelleği belirli bir boyuta başlatmanın hiçbir yolu yoktur.
Çözüm, beklenen kodlamaya bağlı olarak yerine bağımsız değişken olarak veya char[]
Stringgeçirmektirbyte[]
. ile [Out]
işaretlendiğinde dizi, ayrılan dizinin kapasitesini aşmaması koşuluyla çağıran tarafından başvurulabilir ve değiştirilebilir.
Örneğin, Windows GetWindowText
API işlevi (winuser.h içinde tanımlanır) çağıranın, işlevin pencerenin metnini yazdığı sabit uzunlukta bir karakter arabelleği geçirmesini gerektirir. lpString
Bağımsız değişken, boyutu nMaxCount
çağıran tarafından ayrılan arabelleğe işaret etti. Çağıranın arabelleği ayırması ve bağımsız değişkenini nMaxCount
ayrılan arabelleğin boyutuna ayarlaması beklenir. Aşağıdaki örnekte winuser.h dosyasında tanımlanan işlev bildirimi gösterilmektedirGetWindowText
.
int GetWindowText(
HWND hWnd, // Handle to window or control.
LPTStr lpString, // Text buffer.
int nMaxCount // Maximum number of characters to copy.
);
bir char[]
başvurusu kaldırılabilir ve çağıran tarafından değiştirilebilir. Aşağıdaki kod örneği, önceden char[]
ayırmak için nasıl ArrayPool<char>
kullanılabileceğini gösterir.
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
Başka bir çözüm, yerine bağımsız değişken Stringolarak geçirmektirStringBuilder. bir StringBuilder
öğesinin hazırlaması sırasında oluşturulan arabellek, öğesinin kapasitesini StringBuilder
aşmaması koşuluyla çağıran tarafından başvurulabilir ve değiştirilebilir. Sabit uzunlukta da başlatılabilir. Örneğin, için bir StringBuilder
N
arabellek başlatırsanız, marshaller boyut (N
+1) karakterlik bir arabellek sağlar. +1, yönetilmeyen dizenin null bir sonlandırıcıya StringBuilder
sahip olduğunu ancak içermediğini hesaplar.
Not
Genel olarak, performansla ilgileniyorsanız bağımsız değişkenleri geçirmeniz StringBuilder
önerilmez. Daha fazla bilgi için bkz . Dize parametreleri.