Aracılığıyla paylaş


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 outdeğ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 , LPTStrve seçeneklerine izin verilirLPStrLPWStr.

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 StringBuilderaşmaması koşuluyla çağıran tarafından başvurulabilir ve değiştirilebilir. Sabit uzunlukta da başlatılabilir. Örneğin, için bir StringBuilderNarabellek 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.

Ayrıca bkz.