Sdílet prostřednictvím


Výchozí zařazování polí

V aplikaci, která se skládá výhradně ze spravovaného kódu, modul CLR předává typy polí jako parametry In/Out. Naproti tomu interop marshaller předává pole jako Parametry ve výchozím nastavení.

Při optimalizaci připnutí se může při interakci s objekty ve stejném bytě zdát, že pole blittable funguje jako parametr In/Out. Pokud ale později kód exportujete do knihovny typů, která se používá ke generování proxy serveru mezi počítači a tato knihovna se používá k zařazování volání mezi apartmány, můžou se volání vrátit na hodnotu True V chování parametru.

Pole jsou ze své podstaty složitá a rozdíly mezi spravovanými a nespravovanými poli vyžadují více informací než jiné nespravovatelné typy.

Spravovaná pole

Typy spravovaných polí se mohou lišit; System.Array třída je však základní třídou všech typů pole. Třída System.Array má vlastnosti pro určení pořadí, délky a dolní a horní hranice pole, stejně jako metody pro přístup, řazení, vyhledávání, kopírování a vytváření polí.

Tyto typy polí jsou dynamické a nemají odpovídající statický typ definovaný v knihovně základních tříd. Je vhodné si představit každou kombinaci typu prvku a pořadí jako odlišný typ pole. Jednorozměrné pole celých čísel je tedy jiného typu než jednorozměrné pole dvojitých typů. Podobně se dvojrozměrné pole celých čísel liší od jednorozměrného pole celých čísel. Hranice pole nejsou při porovnávání typů považovány za hranice.

Jak ukazuje následující tabulka, každá instance spravovaného pole musí mít konkrétní typ prvku, pořadí a dolní mez.

Typ spravovaného pole Typ prvku Rank Dolní hranice Zápis podpisu
ELEMENT_TYPE_ARRAY Určuje se podle typu. Určeno pořadím. Volitelně je určeno hranicemi. typ [ n,m ]
ELEMENT_TYPE_CLASS Neznámý Neznámý Neznámý System.Array
ELEMENT_TYPE_SZARRAY Určuje se podle typu. 0 0 typ [ n ]

Nespravovaná pole

Nespravovaná pole jsou bezpečná pole ve stylu MODELU COM nebo pole ve stylu C s pevnou nebo proměnlivou délkou. Bezpečná pole jsou pole popisující sama sebe, která nesou typ, pořadí a hranice přidružených dat pole. Matice ve stylu jazyka C jsou jednorozměrná typová pole s pevnou dolní mezí 0. Služba zařazování má omezenou podporu pro oba typy polí.

Předávání parametrů pole do kódu .NET

Pole ve stylu jazyka C i bezpečná pole lze předat kódu .NET z nespravovaného kódu jako bezpečné pole nebo pole ve stylu jazyka C. Následující tabulka ukazuje nespravovanou hodnotu typu a importovaný typ.

Nespravovaný typ Importovaný typ
SafeArray( Typ ) < ELEMENT_TYPE_SZARRAY ConvertedType >

Pořadí = 1, dolní mez = 0. Velikost je známá pouze v případě, že je ve spravovaném podpisu. Bezpečná pole, která nemají pořadí = 1 nebo dolní mez = 0, nelze zařaďovat jako SZARRAY.
Typ [] < ELEMENT_TYPE_SZARRAY ConvertedType >

Pořadí = 1, dolní mez = 0. Velikost je známá pouze v případě, že je ve spravovaném podpisu.

Bezpečná pole

Při importu bezpečného pole z knihovny typů do sestavení .NET se pole převede na jednorozměrné pole známého typu (například int). Stejná pravidla převodu typů, která platí pro parametry, platí také pro prvky pole. Například bezpečné pole typů BSTR se stane spravovanou maticí řetězců a bezpečnou maticí variant se stane spravovanou maticí objektů. Typ prvku SAFEARRAY je zachycen z knihovny typů a uložen v SAFEARRAY hodnotu výčtu UnmanagedType .

Vzhledem k tomu, že pořadí a hranice bezpečného pole nelze určit z knihovny typů, předpokládá se, že pořadí je rovno 1 a dolní mez se předpokládá, že se rovná 0. Pořadí a hranice musí být definovány ve spravovaném podpisu vytvořeném nástrojem Type Library Importer (Tlbimp.exe). Pokud se pořadí předané metodě za běhu liší, SafeArrayRankMismatchException vyvolá se vyvolá. Pokud se typ pole předaného v době běhu liší, SafeArrayTypeMismatchException vyvolá se vyvolá. Následující příklad ukazuje bezpečné pole ve spravovaném a nespravovaném kódu.

Nespravovaný podpis

HRESULT New1([in] SAFEARRAY( int ) ar);
HRESULT New2([in] SAFEARRAY( DATE ) ar);
HRESULT New3([in, out] SAFEARRAY( BSTR ) *ar);

Spravovaný podpis

Sub New1(<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_I4)> _
   ar() As Integer)
Sub New2(<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_DATE)> _
   ar() As DateTime)
Sub New3(ByRef <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_BSTR)> _
   ar() As String)
void New1([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_I4)] int[] ar) ;
void New2([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_DATE)]
   DateTime[] ar);
void New3([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)]
   ref String[] ar);

Multidimenzionální nebo nenulové bezpečné pole lze zařaďovat do spravovaného kódu, pokud je podpis metody vytvořený Tlbimp.exe upraven tak, aby označoval typ prvku ELEMENT_TYPE_ARRAY místo ELEMENT_TYPE_SZARRAY. Alternativně můžete použít přepínač /sysarray s Tlbimp.exe k importu všech polí jako System.Array objektů. V případech, kdy je předané pole známo jako multidimenzionální, můžete upravit kód CIL (Common Intermediate Language) vytvořený Tlbimp.exe a pak ho znovu zkompilovat. Podrobnosti o tom, jak upravit kód CIL, naleznete v tématu Přizpůsobení volatelné obálky modulu runtime.

Pole ve stylu jazyka C

Pokud je pole ve stylu jazyka C importováno z knihovny typů do sestavení .NET, pole se převede na ELEMENT_TYPE_SZARRAY.

Typ prvku pole je určen z knihovny typů a zachován během importu. Stejná pravidla převodu, která platí pro parametry, platí také pro prvky pole. Například pole typů LPStr se stane polem typů String . Tlbimp.exe zachytí typ prvku pole a použije MarshalAsAttribute atribut na parametr.

Maticové pořadí se předpokládá, že se rovná 1. Pokud je pořadí větší než 1, pole se zařadí jako jednorozměrné pole ve sloupcovém hlavním pořadí. Dolní mez se vždy rovná 0.

Knihovny typů můžou obsahovat pole s pevnou nebo proměnlivou délkou. Tlbimp.exe může importovat pouze pole s pevnou délkou z knihoven typů, protože knihovny typů nemají informace potřebné k zařazování polí s proměnnou délkou. U polí s pevnou délkou se velikost naimportuje z knihovny typů a zachytí se v marshalAsAttribute , která se použije u parametru.

Knihovny typů obsahující pole s proměnnou délkou je nutné definovat ručně, jak je znázorněno v následujícím příkladu.

Nespravovaný podpis

HRESULT New1(int ar[10]);
HRESULT New2(double ar[10][20]);
HRESULT New3(LPWStr ar[10]);

Spravovaný podpis

Sub New1(<MarshalAs(UnmanagedType.LPArray, SizeConst=10)> _
   ar() As Integer)
Sub New2(<MarshalAs(UnmanagedType.LPArray, SizeConst=200)> _
   ar() As Double)
Sub New2(<MarshalAs(UnmanagedType.LPArray, _
   ArraySubType=UnmanagedType.LPWStr, SizeConst=10)> _
   ar() As String)
void New1([MarshalAs(UnmanagedType.LPArray, SizeConst=10)] int[] ar);
void New2([MarshalAs(UnmanagedType.LPArray, SizeConst=200)] double[] ar);
void New2([MarshalAs(UnmanagedType.LPArray,
   ArraySubType=UnmanagedType.LPWStr, SizeConst=10)] String[] ar);

I když můžete použít atributy size_is nebo length_is na pole ve zdroji IDL (Interface Definition Language) ke sdělení velikosti klientovi, kompilátor MIDL (Microsoft Interface Definition Language) tyto informace nešířuje do knihovny typů. Bez znalosti velikosti nemůže služba zařazování zprostředkovatele zařazování prvků pole zařaďovat. V důsledku toho se pole s proměnnou délkou importují jako referenční argumenty. Příklad:

Nespravovaný podpis

HRESULT New1(int ar[]);
HRESULT New2(int ArSize, [size_is(ArSize)] double ar[]);
HRESULT New3(int ElemCnt, [length_is(ElemCnt)] LPStr ar[]);

Spravovaný podpis

Sub New1(ByRef ar As Integer)
Sub New2(ByRef ar As Double)
Sub New3(ByRef ar As String)
void New1(ref int ar);
void New2(ref double ar);
void New3(ref String ar);

Velikost pole můžete poskytnout úpravou kódu CIL (Common Intermediate Language) vytvořeného Tlbimp.exe a jeho opětovným zkompilováním. Podrobnosti o tom, jak upravit kód CIL, naleznete v tématu Přizpůsobení volatelné obálky modulu runtime. Chcete-li označit počet prvků v poli, použijte MarshalAsAttribute typ na parametr pole definice spravované metody jedním z následujících způsobů:

  • Identifikujte jiný parametr, který obsahuje počet prvků v poli. Parametry jsou identifikovány podle pozice, počínaje prvním parametrem jako číslem 0.

    Sub [New](ElemCnt As Integer, _
       \<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
       ar() As Integer)
    
    void New(
       int ElemCnt,
       [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] int[] ar );
    
  • Definujte velikost pole jako konstantu. Příklad:

    Sub [New](\<MarshalAs(UnmanagedType.LPArray, SizeConst:=128)> _
       ar() As Integer)
    
    void New(
       [MarshalAs(UnmanagedType.LPArray, SizeConst=128)] int[] ar );
    

Při zařazování polí z nespravovaného kódu na spravovaný kód zkontroluje marshaller marshalAsAttribute přidružený k parametru, aby určil velikost pole. Pokud není zadána velikost pole, je zařazován pouze jeden prvek.

Poznámka:

MarshalAsAttribute nemá žádný vliv na zařazování spravovaných polí na nespravovaný kód. V takovém směru je velikost pole určena vyšetřením. Neexistuje způsob, jak zařadit podmnožinu spravovaného pole.

Interop marshaller používá metody CoTaskMemAlloc a CoTaskMemFree ve Windows nebo malloc a volných metod v jiných operačních systémech k přidělení a načtení paměti. Přidělení paměti prováděné nespravovaným kódem musí také používat tyto metody.

Předávání polí modelu COM

Všechny typy spravovaných polí je možné předat nespravovanému kódu ze spravovaného kódu. V závislosti na spravovaném typu a použitých atributech je možné pole získat přístup jako bezpečné pole nebo pole ve stylu jazyka C, jak je znázorněno v následující tabulce.

Typ spravovaného pole Exportováno jako
< typ ELEMENT_TYPE_SZARRAY > UnmanagedType. SafeArray( typ )

UnmanagedType.LPArray

Do podpisu se zadává typ. Pořadí je vždy 1, dolní mez je vždy 0. Velikost je vždy známa za běhu.
ELEMENT_TYPE_ARRAY pořadí typů < > >[< hranice ] > < UnmanagedType.SafeArray( typ )

UnmanagedType.LPArray

Typ, pořadí, hranice jsou k dispozici v podpisu. Velikost je vždy známa za běhu.
ELEMENT_TYPE_CLASS <System.Array> UT_Interface

UnmanagedType.SafeArray( typ )

Typ, pořadí, hranice a velikost jsou vždy známy za běhu.

V automatizaci OLE existuje omezení týkající se polí struktur, které obsahují LPSTR nebo LPWSTR. Proto musí být pole String zařazována jako UnmanagedType.BSTR. V opačném případě se vyvolá výjimka.

ELEMENT_TYPE_SZARRAY

Pokud je metoda obsahující parametr ELEMENT_TYPE_SZARRAY (jednorozměrné pole) exportována z sestavení .NET do knihovny typů, je parametr pole převeden na SAFEARRAY daného typu. Stejná pravidla převodu platí pro typy prvků pole. Obsah spravovaného pole se automaticky zkopíruje ze spravované paměti do SAFEARRAY. Příklad:

Spravovaný podpis

Sub [New](ar() As Long)
Sub [New](ar() As String)
void New(long[] ar );
void New(String[] ar );

Nespravovaný podpis

HRESULT New([in] SAFEARRAY( long ) ar);
HRESULT New([in] SAFEARRAY( BSTR ) ar);

Pořadí bezpečných polí je vždy 1 a dolní mez je vždy 0. Velikost se určuje za běhu podle velikosti předávaného spravovaného pole.

Pole lze také zařazovat jako pole ve stylu jazyka C pomocí atributu MarshalAsAttribute . Příklad:

Spravovaný podpis

Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
   ar() As Long, size as Integer)
Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
   ar() As String, size as Integer)
Sub [New](<MarshalAs(UnmanagedType.LPArray, _
   ArraySubType= UnmanagedType.LPStr, SizeParamIndex:=1)> _
   ar() As String, size as Integer)
void New([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
   long [] ar, int size );
void New([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
   String [] ar, int size );
void New([MarshalAs(UnmanagedType.LPArray, ArraySubType=
   UnmanagedType.LPStr, SizeParamIndex=1)]
   String [] ar, int size );

Nespravovaný podpis

HRESULT New(long ar[]);
HRESULT New(BSTR ar[]);
HRESULT New(LPStr ar[]);

I když má marshaller informace o délce potřebné k zařazování pole, délka pole se obvykle předává jako samostatný argument pro předání délky volaného.

ELEMENT_TYPE_ARRAY

Při exportu metody obsahující parametr ELEMENT_TYPE_ARRAY ze sestavení .NET do knihovny typů je parametr pole převeden na SAFEARRAY daného typu. Obsah spravovaného pole se automaticky zkopíruje ze spravované paměti do SAFEARRAY. Příklad:

Spravovaný podpis

Sub [New](ar(,) As Long)
Sub [New](ar(,) As String)
void New( long [,] ar );
void New( String [,] ar );

Nespravovaný podpis

HRESULT New([in] SAFEARRAY( long ) ar);
HRESULT New([in] SAFEARRAY( BSTR ) ar);

Pořadí, velikost a hranice bezpečných polí se určují v době běhu podle charakteristik spravovaného pole.

Pole lze také zařazovat jako pole ve stylu jazyka C použitím atributu MarshalAsAttribute . Příklad:

Spravovaný podpis

Sub [New](<MarshalAs(UnmanagedType.LPARRAY, SizeParamIndex:=1)> _
   ar(,) As Long, size As Integer)
Sub [New](<MarshalAs(UnmanagedType.LPARRAY, _
   ArraySubType:=UnmanagedType.LPStr, SizeParamIndex:=1)> _
   ar(,) As String, size As Integer)
void New([MarshalAs(UnmanagedType.LPARRAY, SizeParamIndex=1)]
   long [,] ar, int size );
void New([MarshalAs(UnmanagedType.LPARRAY,
   ArraySubType= UnmanagedType.LPStr, SizeParamIndex=1)]
   String [,] ar, int size );

Nespravovaný podpis

HRESULT New(long ar[]);
HRESULT New(LPStr ar[]);

Vnořené pole nelze zařaďovat. Například následující podpis vygeneruje chybu při exportu s exportem knihovny typů (Tlbexp.exe).

Spravovaný podpis

Sub [New](ar()()() As Long)
void New(long [][][] ar );

<ELEMENT_TYPE_CLASS System.Array>

Při exportu metody obsahující System.Array parametr ze sestavení .NET do knihovny typů je parametr pole převeden na rozhraní _Array . Obsah spravovaného pole je přístupný pouze prostřednictvím metod a vlastností rozhraní _Array . System.Array lze také zařazovat jako SAFEARRAY pomocí atributu MarshalAsAttribute . Při zařazování jako bezpečného pole jsou prvky pole zařazovány jako varianty. Příklad:

Spravovaný podpis

Sub New1( ar As System.Array )
Sub New2( <MarshalAs(UnmanagedType.SafeArray)> ar As System.Array )
void New1( System.Array ar );
void New2( [MarshalAs(UnmanagedType.SafeArray)] System.Array ar );

Nespravovaný podpis

HRESULT New([in] _Array *ar);
HRESULT New([in] SAFEARRAY(VARIANT) ar);

Pole v rámci struktur

Nespravované struktury mohou obsahovat vložená pole. Ve výchozím nastavení jsou tato vložená pole zařazována jako SAFEARRAY. V následujícím příkladu je vložené pole, s1 které je přiděleno přímo uvnitř samotné struktury.

Nespravovaná reprezentace

struct MyStruct {
    short s1[128];
}

Pole můžou být zařazována jako UnmanagedTypepole, což vyžaduje, abyste pole nastavili MarshalAsAttribute . Velikost lze nastavit pouze jako konstantu. Následující kód ukazuje odpovídající spravovanou definici MyStruct.

Public Structure <StructLayout(LayoutKind.Sequential)> MyStruct
   Public <MarshalAs(UnmanagedType.ByValArray, SizeConst := 128)> _
     s1() As Short
End Structure
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct {
   [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)] public short[] s1;
}

Viz také