Marshalling predefinito per gli oggettiDefault Marshaling for Objects

I parametri e i campi tipizzati come System.Object possono essere esposti al codice non gestito come uno dei tipi seguenti:Parameters and fields typed as System.Object can be exposed to unmanaged code as one of the following types:

  • Una variante quando l'oggetto è un parametro.A variant when the object is a parameter.

  • Un'interfaccia quando l'oggetto è un campo della struttura.An interface when the object is a structure field.

Solo l'interoperabilità COM supporta il marshalling per i tipi di oggetto.Only COM interop supports marshaling for object types. Il comportamento predefinito è il marshalling degli oggetti alle varianti COM.The default behavior is to marshal objects to COM variants. Queste regole si applicano solo al tipo Object e non agli oggetti fortemente tipizzati derivanti dalla classe Object.These rules apply only to the type Object and do not apply to strongly typed objects that derive from the Object class.

Questo argomento offre le informazioni aggiuntive seguenti sul marshalling dei tipi di oggetto:This topic provides the following additional information about marshaling object types:

Opzioni di marshallingMarshaling Options

La tabella seguente illustra le opzioni di marshalling per il tipo di dati Object.The following table shows the marshaling options for the Object data type. L'attributo MarshalAsAttribute fornisce alcuni valori di enumerazione UnmanagedType per effettuare il marshalling di oggetti.The MarshalAsAttribute attribute provides several UnmanagedType enumeration values to marshal objects.

Tipo di enumerazioneEnumeration type Descrizione del formato non gestitoDescription of unmanaged format
UnmanagedType.StructUnmanagedType.Struct

(predefinita per i parametri)(default for parameters)
Una variante di tipo COM.A COM-style variant.
UnmanagedType.InterfaceUnmanagedType.Interface Un'interfaccia IDispatch, se possibile; in caso contrario, un'interfaccia IUnknown.An IDispatch interface, if possible; otherwise, an IUnknown interface.
UnmanagedType.IUnknownUnmanagedType.IUnknown

(predefinita per i campi)(default for fields)
Un' interfaccia IUnknown.An IUnknown interface.
UnmanagedType.IDispatchUnmanagedType.IDispatch Un'interfaccia IDispatch.An IDispatch interface.

L'esempio seguente illustra la definizione dell'interfaccia gestita per MarshalObject.The following example shows the managed interface definition for MarshalObject.

Interface MarshalObject  
   Sub SetVariant(o As Object)  
   Sub SetVariantRef(ByRef o As Object)  
   Function GetVariant() As Object  

   Sub SetIDispatch( <MarshalAs(UnmanagedType.IDispatch)> o As Object)  
   Sub SetIDispatchRef(ByRef <MarshalAs(UnmanagedType.IDispatch)> o _  
      As Object)  
   Function GetIDispatch() As <MarshalAs(UnmanagedType.IDispatch)> Object  
   Sub SetIUnknown( <MarshalAs(UnmanagedType.IUnknown)> o As Object)  
   Sub SetIUnknownRef(ByRef <MarshalAs(UnmanagedType.IUnknown)> o _  
      As Object)  
   Function GetIUnknown() As <MarshalAs(UnmanagedType.IUnknown)> Object  
End Interface  
interface MarshalObject {  
   void SetVariant(Object o);  
   void SetVariantRef(ref Object o);  
   Object GetVariant();  

   void SetIDispatch ([MarshalAs(UnmanagedType.IDispatch)]Object o);  
   void SetIDispatchRef([MarshalAs(UnmanagedType.IDispatch)]ref Object o);  
   [MarshalAs(UnmanagedType.IDispatch)] Object GetIDispatch();  
   void SetIUnknown ([MarshalAs(UnmanagedType.IUnknown)]Object o);  
   void SetIUnknownRef([MarshalAs(UnmanagedType.IUnknown)]ref Object o);  
   [MarshalAs(UnmanagedType.IUnknown)] Object GetIUnknown();  
}  

Il codice seguente esporta l'interfaccia MarshalObject in una libreria dei tipi.The following code exports the MarshalObject interface to a type library.

interface MarshalObject {  
   HRESULT SetVariant([in] VARIANT o);  
   HRESULT SetVariantRef([in,out] VARIANT *o);  
   HRESULT GetVariant([out,retval] VARIANT *o)   
   HRESULT SetIDispatch([in] IDispatch *o);  
   HRESULT SetIDispatchRef([in,out] IDispatch **o);  
   HRESULT GetIDispatch([out,retval] IDispatch **o)   
   HRESULT SetIUnknown([in] IUnknown *o);  
   HRESULT SetIUnknownRef([in,out] IUnknown **o);  
   HRESULT GetIUnknown([out,retval] IUnknown **o)   
}  

Nota

Il gestore di marshalling di interoperabilità libera automaticamente gli oggetti allocati nella variante dopo la chiamata.The interop marshaler automatically frees any allocated object inside the variant after the call.

L'esempio seguente illustra un tipo valore formattato.The following example shows a formatted value type.

Public Structure ObjectHolder  
   Dim o1 As Object  
   <MarshalAs(UnmanagedType.IDispatch)> Public o2 As Object  
End Structure  
public struct ObjectHolder {  
   Object o1;  
   [MarshalAs(UnmanagedType.IDispatch)]public Object o2;  
}  

Il codice seguente esporta il tipo formattato in una libreria dei tipi.The following code exports the formatted type to a type library.

struct ObjectHolder {  
   VARIANT o1;  
   IDispatch *o2;  
}  

Marshalling dell'oggetto all'interfacciaMarshaling Object to Interface

Quando un oggetto viene esposto a COM come interfaccia, tale interfaccia è l'interfaccia di classe del tipo gestito Object (interfaccia _Object).When an object is exposed to COM as an interface, that interface is the class interface for the managed type Object (the _Object interface). Questa interfaccia viene tipizzata come IDispatch (UnmanagedType) o IUnknown (UnmanagedType.IUnknown) nella libreria dei tipi risultante.This interface is typed as an IDispatch (UnmanagedType) or an IUnknown (UnmanagedType.IUnknown) in the resulting type library. I client COM possono richiamare in modo dinamico i membri della classe gestita o eventuali membri implementati dalle classi derivate tramite l'interfaccia _Object.COM clients can dynamically invoke the members of the managed class or any members implemented by its derived classes through the _Object interface. Il client può anche chiamare QueryInterface per ottenere le altre interfacce implementate in modo esplicito dal tipo gestito.The client can also call QueryInterface to obtain any other interface explicitly implemented by the managed type.

Marshalling dell'oggetto alla varianteMarshaling Object to Variant

Quando viene effettuato il marshalling di un oggetto a una variante, il tipo di variante interno viene determinato in fase di esecuzione, in base alle regole seguenti:When an object is marshaled to a variant, the internal variant type is determined at run time, based on the following rules:

  • Se il riferimento all'oggetto è null (Nothing in Visual Basic), viene effettuato il marshalling dell'oggetto a una variante di tipo VT_EMPTY.If the object reference is null (Nothing in Visual Basic), the object is marshaled to a variant of type VT_EMPTY.

  • Se l'oggetto è un'istanza di un tipo elencato nella tabella seguente, il tipo di variante risultante viene determinato dalle regole incluse nel gestore di marshalling e visualizzate nella tabella.If the object is an instance of any type listed in the following table, the resulting variant type is determined by the rules built into the marshaler and shown in the table.

  • Gli altri oggetti che devono controllare in modo esplicito il comportamento di marshalling possono implementare l'interfaccia IConvertible.Other objects that need to explicitly control the marshaling behavior can implement the IConvertible interface. In tal caso, il tipo di variante viene determinato dal codice del tipo restituito dal metodo IConvertible.GetTypeCode.In that case, the variant type is determined by the type code returned from the IConvertible.GetTypeCode method. In caso contrario, viene effettuato il marshalling dell'oggetto come variante di tipo VT_UNKNOWN.Otherwise, the object is marshaled as a variant of type VT_UNKNOWN.

Marshalling di tipi di sistema alla varianteMarshaling System Types to Variant

La tabella seguente illustra i tipi di oggetto gestito e i corrispondenti tipi di varianti COM.The following table shows managed object types and their corresponding COM variant types. Questi tipi vengono convertiti solo quando la firma del metodo chiamato è di tipo System.Object.These types are converted only when the signature of the method being called is of type System.Object.

Tipo di oggettoObject type Tipo di variante COMCOM variant type
Riferimento all'oggetto null (Nothing in Visual Basic).Null object reference (Nothing in Visual Basic). VT_EMPTYVT_EMPTY
System.DBNull VT_NULLVT_NULL
System.Runtime.InteropServices.ErrorWrapper VT_ERRORVT_ERROR
System.Reflection.Missing VT_ERROR con E_PARAMNOTFOUNDVT_ERROR with E_PARAMNOTFOUND
System.Runtime.InteropServices.DispatchWrapper VT_DISPATCHVT_DISPATCH
System.Runtime.InteropServices.UnknownWrapper VT_UNKNOWNVT_UNKNOWN
System.Runtime.InteropServices.CurrencyWrapper VT_CYVT_CY
System.Boolean VT_BOOLVT_BOOL
System.SByte VT_I1VT_I1
System.Byte VT_UI1VT_UI1
System.Int16 VT_I2VT_I2
System.UInt16 VT_UI2VT_UI2
System.Int32 VT_I4VT_I4
System.UInt32 VT_UI4VT_UI4
System.Int64 VT_I8VT_I8
System.UInt64 VT_UI8VT_UI8
System.Single VT_R4VT_R4
System.Double VT_R8VT_R8
System.Decimal VT_DECIMALVT_DECIMAL
System.DateTime VT_DATEVT_DATE
System.String VT_BSTRVT_BSTR
System.IntPtr VT_INTVT_INT
System.UIntPtr VT_UINTVT_UINT
System.Array VT_ARRAYVT_ARRAY

Usando l'interfaccia MarshalObject definita nell'esempio precedente, l'esempio di codice seguente illustra come passare diversi tipi di varianti a un server COM.Using the MarshalObject interface defined in the previous example, the following code example demonstrates how to pass various types of variants to a COM server.

Dim mo As New MarshalObject()  
mo.SetVariant(Nothing)         ' Marshal as variant of type VT_EMPTY.  
mo.SetVariant(System.DBNull.Value) ' Marshal as variant of type VT_NULL.  
mo.SetVariant(CInt(27))        ' Marshal as variant of type VT_I2.  
mo.SetVariant(CLng(27))        ' Marshal as variant of type VT_I4.  
mo.SetVariant(CSng(27.0))      ' Marshal as variant of type VT_R4.  
mo.SetVariant(CDbl(27.0))      ' Marshal as variant of type VT_R8.  
MarshalObject mo = new MarshalObject();  
mo.SetVariant(null);            // Marshal as variant of type VT_EMPTY.  
mo.SetVariant(System.DBNull.Value); // Marshal as variant of type VT_NULL.  
mo.SetVariant((int)27);          // Marshal as variant of type VT_I2.  
mo.SetVariant((long)27);          // Marshal as variant of type VT_I4.  
mo.SetVariant((single)27.0);   // Marshal as variant of type VT_R4.  
mo.SetVariant((double)27.0);   // Marshal as variant of type VT_R8.  

È possibile effettuare il marshalling dei tipi COM privi di tipi gestiti corrispondenti usando classi wrapper, ad esempio ErrorWrapper, DispatchWrapper, UnknownWrapper e CurrencyWrapper.COM types that do not have corresponding managed types can be marshaled using wrapper classes such as ErrorWrapper, DispatchWrapper, UnknownWrapper, and CurrencyWrapper. L'esempio di codice seguente illustra come usare questi wrapper per passare diversi tipi di varianti a un server COM.The following code example demonstrates how to use these wrappers to pass various types of variants to a COM server.

Imports System.Runtime.InteropServices  
' Pass inew as a variant of type VT_UNKNOWN interface.  
mo.SetVariant(New UnknownWrapper(inew))  
' Pass inew as a variant of type VT_DISPATCH interface.  
mo.SetVariant(New DispatchWrapper(inew))  
' Pass a value as a variant of type VT_ERROR interface.  
mo.SetVariant(New ErrorWrapper(&H80054002))  
' Pass a value as a variant of type VT_CURRENCY interface.  
mo.SetVariant(New CurrencyWrapper(New Decimal(5.25)))  
using System.Runtime.InteropServices;  
// Pass inew as a variant of type VT_UNKNOWN interface.  
mo.SetVariant(new UnknownWrapper(inew));  
// Pass inew as a variant of type VT_DISPATCH interface.  
mo.SetVariant(new DispatchWrapper(inew));  
// Pass a value as a variant of type VT_ERROR interface.  
mo.SetVariant(new ErrorWrapper(0x80054002));  
// Pass a value as a variant of type VT_CURRENCY interface.  
mo.SetVariant(new CurrencyWrapper(new Decimal(5.25)));  

Le classi wrapper vengono definite nello spazio dei nomi System.Runtime.InteropServices.The wrapper classes are defined in the System.Runtime.InteropServices namespace.

Marshalling dell'interfaccia IConvertible alla varianteMarshaling the IConvertible Interface to Variant

I tipi diversi da quelli elencati nella sezione precedente possono controllare come viene effettuato il marshalling implementando l'interfaccia IConvertible.Types other than those listed in the previous section can control how they are marshaled by implementing the IConvertible interface. Se l'oggetto implementa l'interfaccia IConvertible, il tipo di variante COM viene determinato in fase di esecuzione dal valore dell'enumerazione TypeCode restituita dal metodo IConvertible.GetTypeCode.If the object implements the IConvertible interface, the COM variant type is determined at run time by the value of the TypeCode enumeration returned from the IConvertible.GetTypeCode method.

La tabella seguente illustra i possibili valori per l'enumerazione TypeCode e il tipo di variante COM corrispondente per ogni valore.The following table shows the possible values for the TypeCode enumeration and the corresponding COM variant type for each value.

TypeCodeTypeCode Tipo di variante COMCOM variant type
TypeCode.EmptyTypeCode.Empty VT_EMPTYVT_EMPTY
TypeCode.ObjectTypeCode.Object VT_UNKNOWNVT_UNKNOWN
TypeCode.DBNullTypeCode.DBNull VT_NULLVT_NULL
TypeCode.BooleanTypeCode.Boolean VT_BOOLVT_BOOL
TypeCode.CharTypeCode.Char VT_UI2VT_UI2
TypeCode.SbyteTypeCode.Sbyte VT_I1VT_I1
TypeCode.ByteTypeCode.Byte VT_UI1VT_UI1
TypeCode.Int16TypeCode.Int16 VT_I2VT_I2
TypeCode.UInt16TypeCode.UInt16 VT_UI2VT_UI2
TypeCode.Int32TypeCode.Int32 VT_I4VT_I4
TypeCode.UInt32TypeCode.UInt32 VT_UI4VT_UI4
TypeCode.Int64TypeCode.Int64 VT_I8VT_I8
TypeCode.UInt64TypeCode.UInt64 VT_UI8VT_UI8
TypeCode.SingleTypeCode.Single VT_R4VT_R4
TypeCode.DoubleTypeCode.Double VT_R8VT_R8
TypeCode.DecimalTypeCode.Decimal VT_DECIMALVT_DECIMAL
TypeCode.DateTimeTypeCode.DateTime VT_DATEVT_DATE
TypeCode.StringTypeCode.String VT_BSTRVT_BSTR
Non supportato.Not supported. VT_INTVT_INT
Non supportato.Not supported. VT_UINTVT_UINT
Non supportato.Not supported. VT_ARRAYVT_ARRAY
Non supportato.Not supported. VT_RECORDVT_RECORD
Non supportato.Not supported. VT_CYVT_CY
Non supportato.Not supported. VT_VARIANTVT_VARIANT

Il valore della variante COM viene determinato chiamando l'interfaccia IConvertible.To Type, dove To Type è la routine di conversione che corrisponde al tipo restituito da IConvertible.GetTypeCode.The value of the COM variant is determined by calling the IConvertible.To Type interface, where To Type is the conversion routine that corresponds to the type that was returned from IConvertible.GetTypeCode. Ad esempio, il marshalling di un oggetto che restituisce TypeCode.Double da IConvertible.GetTypeCode viene effettuato come variante COM di tipo VT_R8.For example, an object that returns TypeCode.Double from IConvertible.GetTypeCode is marshaled as a COM variant of type VT_R8. Per ottenere il valore della variante (archiviata nel campo dblVal della variante COM), è possibile eseguire il cast all'interfaccia IConvertible e chiamare il metodo ToDouble.You can obtain the value of the variant (stored in the dblVal field of the COM variant) by casting to the IConvertible interface and calling the ToDouble method.

Marshalling della variante all'oggettoMarshaling Variant to Object

Quando si effettua il marshalling di una variante a un oggetto, il tipo e a volte il valore della variante di cui viene effettuato il marshalling determinano il tipo dell'oggetto prodotto.When marshaling a variant to an object, the type, and sometimes the value, of the marshaled variant determines the type of object produced. La tabella seguente identifica tale tipo di variante e il tipo di oggetto corrispondente creato dal gestore di marshalling quando una variante viene passata da COM a .NET Framework.The following table identifies each variant type and the corresponding object type that the marshaler creates when a variant is passed from COM to the .NET Framework.

Tipo di variante COMCOM variant type Tipo di oggettoObject type
VT_EMPTYVT_EMPTY Riferimento all'oggetto null (Nothing in Visual Basic).Null object reference (Nothing in Visual Basic).
VT_NULLVT_NULL System.DBNull
VT_DISPATCHVT_DISPATCH System.__ComObject o null se (pdispVal == null)System.__ComObject or null if (pdispVal == null)
VT_UNKNOWNVT_UNKNOWN System.__ComObject o null se (punkVal == null)System.__ComObject or null if (punkVal == null)
VT_ERRORVT_ERROR System.UInt32
VT_BOOLVT_BOOL System.Boolean
VT_I1VT_I1 System.SByte
VT_UI1VT_UI1 System.Byte
VT_I2VT_I2 System.Int16
VT_UI2VT_UI2 System.UInt16
VT_I4VT_I4 System.Int32
VT_UI4VT_UI4 System.UInt32
VT_I8VT_I8 System.Int64
VT_UI8VT_UI8 System.UInt64
VT_R4VT_R4 System.Single
VT_R8VT_R8 System.Double
VT_DECIMALVT_DECIMAL System.Decimal
VT_DATEVT_DATE System.DateTime
VT_BSTRVT_BSTR System.String
VT_INTVT_INT System.Int32
VT_UINTVT_UINT System.UInt32
VT_ARRAY | VT_*VT_ARRAY | VT_* System.Array
VT_CYVT_CY System.Decimal
VT_RECORDVT_RECORD Tipo valore boxed corrispondente.Corresponding boxed value type.
VT_VARIANTVT_VARIANT Non supportato.Not supported.

I tipi di variante passati da COM al codice gestito e quindi di nuovo a COM potrebbero non conservare lo stesso tipo di variante per tutta la durata della chiamata.Variant types passed from COM to managed code and then back to COM might not retain the same variant type for the duration of the call. Si consideri che cosa accade quando una variante di tipo VT_DISPATCH viene passata da COM a .NET Framework.Consider what happens when a variant of type VT_DISPATCH is passed from COM to the .NET Framework. Durante il marshalling, la variante viene convertita in System.Object.During marshaling, the variant is converted to a System.Object. Se Object viene quindi passato nuovamente a COM, ne viene effettuato il marshalling a una variante di tipo VT_UNKNOWN.If the Object is then passed back to COM, it is marshaled back to a variant of type VT_UNKNOWN. Non esiste garanzia che la variante prodotta quando viene effettuato il marshalling di un oggetto dal codice gestito a COM sarà dello stesso tipo della variante usata inizialmente per produrre l'oggetto.There is no guarantee that the variant produced when an object is marshaled from managed code to COM will be the same type as the variant initially used to produce the object.

Marshalling di varianti ByRefMarshaling ByRef Variants

Anche se le varianti in sé possono essere passate in base al valore o al riferimento, è anche possibile usare il flag VT_BYREF con qualsiasi variante per indicare che i contenuti della variante verranno passati in base al riferimento invece che al valore.Although variants themselves can be passed by value or by reference, the VT_BYREF flag can also be used with any variant type to indicate that the contents of the variant are being passed by reference instead of by value. La differenza tra il marshalling delle varianti in base al riferimento e il marshalling di una variante con il flag VT_BYREF impostato può risultare poco chiara.The difference between marshaling variants by reference and marshaling a variant with the VT_BYREF flag set can be confusing. La figura seguente illustra le differenze.The following illustration clarifies the differences.

Variante passata allo stackVariant passed on the stack
Varianti passate per valore e per riferimentoVariants passed by value and by reference

Comportamento predefinito per il marshalling di oggetti e varianti per valoreDefault behavior for marshaling objects and variants by value

  • Quando si passano gli oggetti dal codice gestito a COM, i contenuti dell'oggetto vengono copiati in una nuova variante creata dal gestore di marshalling, usando le regole definite in Marshalling dell'oggetto alla variante.When passing objects from managed code to COM, the contents of the object are copied into a new variant created by the marshaler, using the rules defined in Marshaling Object to Variant. Le modifiche apportate alla variante sul lato non gestito non vengono propagate all'oggetto originale al ritorno dalla chiamata.Changes made to the variant on the unmanaged side are not propagated back to the original object on return from the call.

  • Quando si passano le varianti da COM al codice gestito, i contenuti della variante vengono copiati in un nuovo oggetto creato, usando le regole definite in Marshalling della variante all'oggetto.When passing variants from COM to managed code, the contents of the variant are copied to a newly created object, using the rules defined in Marshaling Variant to Object. Le modifiche apportate all'oggetto sul lato gestito non vengono propagate alla variante originale al ritorno dalla chiamata.Changes made to the object on the managed side are not propagated back to the original variant on return from the call.

Comportamento predefinito per il marshalling di oggetti e varianti per riferimentoDefault behavior for marshaling objects and variants by reference

Per propagare le modifiche al chiamante, i parametri devono essere passati per riferimento.To propagate changes back to the caller, the parameters must be passed by reference. È ad esempio possibile usare la parola chiave ref in C# (o ByRef nel codice gestito di Visual Basic) per passare i parametri per riferimento.For example, you can use the ref keyword in C# (or ByRef in Visual Basic managed code) to pass parameters by reference. In COM i parametri per riferimento vengono passati usando un puntatore, ad esempio una variante \*.In COM, reference parameters are passed using a pointer such as a variant \*.

  • Quando si passa un oggetto a COM per riferimento, il gestore di marshalling crea una nuova variante e copia i contenuti del riferimento all'oggetto nella variante prima che venga effettuata la chiamata.When passing an object to COM by reference, the marshaler creates a new variant and copies the contents of the object reference into the variant before the call is made. La variante viene passata alla funzione non gestita in cui l'utente può modificare i contenuti della variante.The variant is passed to the unmanaged function where the user is free to change the contents of the variant. Al ritorno dalla chiamata, le modifiche apportate alla variante sul lato non gestito vengono propagate all'oggetto originale.On return from the call, any changes made to the variant on the unmanaged side are propagated back to the original object. Se il tipo della variante è diverso dal tipo della variante passata alla chiamata, le modifiche vengono propagate a un oggetto di tipo diverso,If the type of the variant differs from the type of the variant passed to the call, then the changes are propagated back to an object of a different type. ovvero il tipo dell'oggetto passato nella chiamata può essere diverso dal tipo dell'oggetto restituito dalla chiamata.That is, the type of the object passed into the call can differ from the type of the object returned from the call.

  • Quando si passa una variante al codice gestito per riferimento, il gestore di marshalling crea un nuovo oggetto e copia i contenuti della variante nell'oggetto prima di effettuare la chiamata.When passing a variant to managed code by reference, the marshaler creates a new object and copies the contents of the variant into the object before making the call. Un riferimento all'oggetto viene passato alla funzione non gestita, in cui l'utente può modificare l'oggetto.A reference to the object is passed to the managed function, where the user is free to change the object. Al ritorno dalla chiamata, le modifiche apportate all'oggetto di riferimento vengono propagate alla variante originale.On return from the call, any changes made to the referenced object are propagated back to the original variant. Se il tipo dell'oggetto è diverso dal tipo dell'oggetto passato alla chiamata, il tipo della variante originale viene modificato e il valore viene propagato nella variante.If the type of the object differs from the type of the object passed in to the call, the type of the original variant is changed and the value is propagated back into the variant. Anche in questo caso il tipo della variante passata nella chiamata può essere diverso dal tipo della variante restituita dalla chiamata.Again, the type of the variant passed into the call can differ from the type of the variant returned from the call.

Comportamento predefinito per il marshalling di una variante con il flag VT_BYREF impostatoDefault behavior for marshaling a variant with the VT_BYREF flag set

  • Una variante che viene passata al codice gestito per valore può avere il flag VT_BYREF impostato per indicare che la variante contiene un riferimento invece che un valore.A variant being passed to managed code by value can have the VT_BYREF flag set to indicate that the variant contains a reference instead of a value. In questo caso, viene ancora effettuato il marshalling della variante a un oggetto perché la variante verrà passata per valore.In this case, the variant is still marshaled to an object because the variant is being passed by value. Il gestore di marshalling dereferenzia automaticamente i contenuti della variante e la copia in un nuovo oggetto creato prima di eseguire la chiamata.The marshaler automatically dereferences the contents of the variant and copies it into a newly created object before making the call. L'oggetto viene quindi passato nella funzione gestita, tuttavia, al ritorno dalla chiamata, l'oggetto non viene propagato nella variante originale.The object is then passed into the managed function; however, on return from the call, the object is not propagated back into the original variant. Le modifiche apportate all'oggetto gestito vengono perse.Changes made to the managed object are lost.

    Attenzione

    Non è possibile modificare il valore di una variante passata per valore, anche se la variante ha il flag VT_BYREF impostato.There is no way to change the value of a variant passed by value, even if the variant has the VT_BYREF flag set.

  • Una variante che viene passata al codice gestito per riferimento può anche avere il flag VT_BYREF impostato per indicare che la variante contiene un altro riferimento.A variant being passed to managed code by reference can also have the VT_BYREF flag set to indicate that the variant contains another reference. In questo caso, viene effettuato il marshalling della variante a un oggetto ref perché la variante verrà passata per riferimento.If it does, the variant is marshaled to a ref object because the variant is being passed by reference. Il gestore di marshalling dereferenzia automaticamente i contenuti della variante e la copia in un nuovo oggetto creato prima di eseguire la chiamata.The marshaler automatically dereferences the contents of the variant and copies it into a newly created object before making the call. Al ritorno dalla chiamata, il valore dell'oggetto viene propagato al riferimento nella variante originale solo se l'oggetto è dello stesso tipo dell'oggetto passato,On return from the call, the value of the object is propagated back to the reference within the original variant only if the object is the same type as the object passed in. ovvero la propagazione non modifica il tipo di una variante con il flag VT_BYREF impostato.That is, propagation does not change the type of a variant with the VT_BYREF flag set. Se il tipo dell'oggetto viene modificato durante la chiamata, al ritorno dalla chiamata viene generata un'eccezione InvalidCastException.If the type of the object is changed during the call, an InvalidCastException occurs on return from the call.

La tabella seguente riepiloga le regole di propagazione per varianti e oggetti.The following table summarizes the propagation rules for variants and objects.

DaFrom ATo Modifiche propagateChanges propagated back
Variante vVariant v Oggetto oObject o NeverNever
Oggetto oObject o Variante vVariant v NeverNever
Variante \* pvVariant \* pv Oggetto ref oRef Object o SempreAlways
Oggetto ref oRef object o Variante \* pvVariant \* pv SempreAlways
Variante v (VT_BYREF | VT_*)Variant v (VT_BYREF | VT_*) Oggetto oObject o NeverNever
Variante v (VT_BYREF | VT_)Variant v (VT_BYREF | VT_) Oggetto ref oRef Object o Solo se il tipo non è stato modificato.Only if the type has not changed.

Vedere ancheSee Also

Comportamento di marshalling predefinitoDefault Marshaling Behavior
Tipi copiabili e non copiabiliBlittable and Non-Blittable Types
Attributi direzionaliDirectional Attributes
Copia e bloccoCopying and Pinning