Маршалинг по умолчанию для объектовDefault Marshaling for Objects

Параметры и поля, типизированные как System.Object, могут предоставляться в неуправляемый код в виде одного из следующих типов:Parameters and fields typed as System.Object can be exposed to unmanaged code as one of the following types:

  • Вариант, если объект является параметром.A variant when the object is a parameter.

  • Интерфейс, если объект является полем структуры.An interface when the object is a structure field.

Маршалинг для типов объектов поддерживается только для COM-взаимодействия.Only COM interop supports marshaling for object types. По умолчанию выполняется маршалинг объектов в варианты COM.The default behavior is to marshal objects to COM variants. Эти правила применяются только к типу Object и не относятся к строго типизированным объектам, производным от класса Object.These rules apply only to the type Object and do not apply to strongly typed objects that derive from the Object class.

Маршалинг параметровMarshaling Options

В следующей таблице показаны параметры маршалинга для типа данных Object.The following table shows the marshaling options for the Object data type. Атрибут MarshalAsAttribute предоставляет несколько значений перечисления UnmanagedType для маршалинга объектов.The MarshalAsAttribute attribute provides several UnmanagedType enumeration values to marshal objects.

Тип перечисленияEnumeration type Описание неуправляемого форматаDescription of unmanaged format
UnmanagedType.StructUnmanagedType.Struct

(по умолчанию для параметров)(default for parameters)
Вариант в стиле COM.A COM-style variant.
UnmanagedType.InterfaceUnmanagedType.Interface Интерфейс IDispatch, если возможно. В противном случае интерфейс IUnknown.An IDispatch interface, if possible; otherwise, an IUnknown interface.
UnmanagedType.IUnknownUnmanagedType.IUnknown

(по умолчанию для полей)(default for fields)
Интерфейс IUnknown.An IUnknown interface.
UnmanagedType.IDispatchUnmanagedType.IDispatch Интерфейс IDispatch.An IDispatch interface.

В следующем примере показано определение управляемого интерфейса для 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();
}

Следующий пример кода экспортирует интерфейс MarshalObject в библиотеку типов.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)
}

Примечание

Маршалер взаимодействия после вызова автоматически высвобождает любой выделенный объект внутри варианта.The interop marshaler automatically frees any allocated object inside the variant after the call.

В следующем примере показан форматированный тип значения.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;
}

Следующий пример кода экспортирует форматированный тип в библиотеку типов.The following code exports the formatted type to a type library.

struct ObjectHolder {
   VARIANT o1;
   IDispatch *o2;
}

Маршалинг объекта в интерфейсMarshaling Object to Interface

Если объект предоставляется модели COM в виде интерфейса, это будет интерфейс класса для управляемого типа Object (интерфейс _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). В полученной библиотеке типов этот интерфейс типизируется как IDispatch (UnmanagedType) или IUnknown (UnmanagedType.IUnknown).This interface is typed as an IDispatch (UnmanagedType) or an IUnknown (UnmanagedType.IUnknown) in the resulting type library. Клиенты COM могут динамически вызывать члены управляемого класса или любые члены, реализуемые его производными классами, используя интерфейс _Object.COM clients can dynamically invoke the members of the managed class or any members implemented by its derived classes through the _Object interface. Клиент также может вызывать QueryInterface для получения любого другого интерфейса, явно реализуемого управляемым типом.The client can also call QueryInterface to obtain any other interface explicitly implemented by the managed type.

Маршалинг объекта в вариантMarshaling Object to Variant

При маршалинге объекта в вариант внутренний тип варианта определяется во время выполнения на основе следующих правил:When an object is marshaled to a variant, the internal variant type is determined at run time, based on the following rules:

  • Если ссылка на объект имеет значение NULL (Nothing в Visual Basic), выполняется маршалинг объекта в вариант типа VT_EMPTY.If the object reference is null (Nothing in Visual Basic), the object is marshaled to a variant of type VT_EMPTY.

  • Если объект является экземпляром любого типа, представленного в следующей таблице, итоговый тип варианта определяется встроенными правилами маршалера, которые показаны в таблице.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.

  • Другие объекты, которым требуется явное управление поведением маршалинга, могут реализовывать интерфейс IConvertible.Other objects that need to explicitly control the marshaling behavior can implement the IConvertible interface. В этом случае тип варианта определяется в соответствии с кодом типа, возвращаемым из метода IConvertible.GetTypeCode.In that case, the variant type is determined by the type code returned from the IConvertible.GetTypeCode method. В противном случае выполняется маршалинг объекта в виде варианта типа VT_UNKNOWN.Otherwise, the object is marshaled as a variant of type VT_UNKNOWN.

Маршалинг системных типов в вариантMarshaling System Types to Variant

В следующей таблице показаны управляемые типы объектов и соответствующие им варианты модели COM.The following table shows managed object types and their corresponding COM variant types. Эти типы преобразуются только в том случае, если сигнатура вызываемого метода относится к типу System.Object.These types are converted only when the signature of the method being called is of type System.Object.

Тип объектаObject type Тип варианта COMCOM variant type
Ссылка на объект NULL (Nothing в 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 с 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

В следующем примере кода с помощью интерфейса MarshalObject демонстрируется передача различных типов вариантов на 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.

Маршалинг типов COM, у которых нет соответствующих управляемых типов, может осуществляться с использованием классов-оболочек, таких как ErrorWrapper, DispatchWrapper, UnknownWrapper и CurrencyWrapper.COM types that do not have corresponding managed types can be marshaled using wrapper classes such as ErrorWrapper, DispatchWrapper, UnknownWrapper, and CurrencyWrapper. В следующем примере кода демонстрируется использование этих классов-оболочек для передачи различных типов вариантов на 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)));

Классы-оболочки определяются в пространстве имен System.Runtime.InteropServices.The wrapper classes are defined in the System.Runtime.InteropServices namespace.

Маршалинг интерфейса IConvertible в вариантMarshaling the IConvertible Interface to Variant

Типы, которые не приведены в предыдущем разделе, могут управлять маршалингом посредством реализации интерфейса IConvertible.Types other than those listed in the previous section can control how they are marshaled by implementing the IConvertible interface. Если объект реализует интерфейс IConvertible, тип варианта COM определяется во время выполнения на основе значения перечисления TypeCode, которое возвращается методом 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.

В следующей таблице показаны возможные значения перечисления TypeCode и соответствующие им типы вариантов COM.The following table shows the possible values for the TypeCode enumeration and the corresponding COM variant type for each value.

Код типаTypeCode Тип варианта 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
Не поддерживается.Not supported. VT_INTVT_INT
Не поддерживается.Not supported. VT_UINTVT_UINT
Не поддерживается.Not supported. VT_ARRAYVT_ARRAY
Не поддерживается.Not supported. VT_RECORDVT_RECORD
Не поддерживается.Not supported. VT_CYVT_CY
Не поддерживается.Not supported. VT_VARIANTVT_VARIANT

Значение варианта COM определяется посредством вызова интерфейса IConvertible.To Type, в котором To Type — это подпрограмма преобразования, которая соответствует типу, возвращаемому из 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. Например, объект, который возвращает TypeCode.Double из IConvertible.GetTypeCode, маршалируется как вариант COM типа VT_R8.For example, an object that returns TypeCode.Double from IConvertible.GetTypeCode is marshaled as a COM variant of type VT_R8. Чтобы получить значение варианта (хранится в поле dblVal варианта COM), можно выполнить приведение к интерфейсу IConvertible и вызвать метод 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.

Маршалинг варианта в объектMarshaling Variant to Object

При маршалинге варианта в объект тип (а в некоторых случаях и значение) маршалированного варианта определяет тип получаемого объекта.When marshaling a variant to an object, the type, and sometimes the value, of the marshaled variant determines the type of object produced. В следующей таблице показаны типы вариантов и соответствующие им типы объектов, которые создаются маршалером при передаче варианта из COM в .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.

Тип варианта COMCOM variant type Тип объектаObject type
VT_EMPTYVT_EMPTY Ссылка на объект NULL (Nothing в Visual Basic).Null object reference (Nothing in Visual Basic).
VT_NULLVT_NULL System.DBNull
VT_DISPATCHVT_DISPATCH System.__ComObject или значение NULL если (pdispVal == null)System.__ComObject or null if (pdispVal == null)
VT_UNKNOWNVT_UNKNOWN System.__ComObject или значение NULL если (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 Соответствующий тип упакованного значения.Corresponding boxed value type.
VT_VARIANTVT_VARIANT Не поддерживается.Not supported.

Типы вариантов, передаваемые из модели COM в управляемый код и обратно в COM, могут не сохранять тип варианта во время вызова.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. Рассмотрим, что произойдет при передаче типа варианта VT_DISPATCH из модели COM в .NET Framework.Consider what happens when a variant of type VT_DISPATCH is passed from COM to the .NET Framework. Во время маршалинга вариант преобразуется в System.Object.During marshaling, the variant is converted to a System.Object. Если затем Object возвращается в COM, выполняется его обратный маршалинг в вариант типа VT_UNKNOWN.If the Object is then passed back to COM, it is marshaled back to a variant of type VT_UNKNOWN. При этом не гарантируется, что вариант, полученный при маршалинге объекта из управляемого кода в COM, будет иметь тот же тип, что и вариант, изначально использованный для создания объекта.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.

Маршалинг вариантов ByRefMarshaling ByRef Variants

Сами по себе варианты могут передаваться по значению или по ссылке. Несмотря на это, также можно использовать флаг VT_BYREF с любым типом варианта, чтобы указать, что содержимое варианта передается по ссылке, а не по значению.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. Разница между маршалингом вариантов по ссылке и с установленным флагом VT_BYREF может показаться не очевидной.The difference between marshaling variants by reference and marshaling a variant with the VT_BYREF flag set can be confusing. На следующем рисунке показаны различия между этими способами:The following illustration clarifies the differences:

Схема, показывающая вариант, передающийся по стеку.Diagram that shows variant passed on the stack. Варианты, передаваемые по значению и по ссылкеVariants passed by value and by reference

Поведение по умолчанию при маршалинге объектов и вариантов по значениюDefault behavior for marshaling objects and variants by value

  • При передаче объектов из управляемого кода в COM содержимое объекта копируется в новый вариант, создаваемый маршалером, с использованием правил, которые определены в разделе Маршалинг объекта в вариант.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. Изменения, внесенные в вариант в неуправляемом коде, не применяются к исходному объекту после возврата из вызова.Changes made to the variant on the unmanaged side are not propagated back to the original object on return from the call.

  • При передаче вариантов из COM в управляемый код содержимое варианта копируется в создаваемый объект с использованием правил, которые определены в разделе Маршалинг варианта в объект.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. Изменения, внесенные в объект в управляемом коде, не применяются к исходному варианту после возврата из вызова.Changes made to the object on the managed side are not propagated back to the original variant on return from the call.

Поведение по умолчанию при маршалинге объектов и вариантов по ссылкеDefault behavior for marshaling objects and variants by reference

Для распространения изменений в вызывающем объекте параметры необходимо передавать по ссылке.To propagate changes back to the caller, the parameters must be passed by reference. Например, можно использовать ключевое слово ref в C# (или ByRef в управляемом коде Visual Basic) для передачи параметров по ссылке.For example, you can use the ref keyword in C# (or ByRef in Visual Basic managed code) to pass parameters by reference. В модели COM ссылочные параметры передаются с использованием указателя, например variant * .In COM, reference parameters are passed using a pointer such as a variant *.

  • При передаче объекта в COM по ссылке маршалер создает новый вариант и копирует содержимое ссылки на объект в вариант до того, как будет выполнен вызов.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. Вариант передается в неуправляемую функцию, в которой пользователь может изменять его содержимое.The variant is passed to the unmanaged function where the user is free to change the contents of the variant. После возврата из вызова изменения, внесенные в вариант в неуправляемом коде, применяются к исходному объекту.On return from the call, any changes made to the variant on the unmanaged side are propagated back to the original object. Если тип варианта отличается от типа варианта, переданного в вызов, изменения применяются к объекту другого типа.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. Таким образом, тип переданного в вызов объекта может отличаться от типа объекта, возвращаемого из вызова.That is, the type of the object passed into the call can differ from the type of the object returned from the call.

  • При передаче варианта в управляемый код по ссылке маршалер создает новый объект и копирует содержимое варианта в объект до того, как будет выполнен вызов.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. Ссылка на объект передается в управляемую функцию, в которой пользователь может изменять сам объект.A reference to the object is passed to the managed function, where the user is free to change the object. После возврата из вызова изменения, внесенные в указываемый по ссылке объект, применяются к исходному варианту.On return from the call, any changes made to the referenced object are propagated back to the original variant. Если тип объекта отличается от типа объекта, переданного в вызов, тип исходного варианта изменяется и значение передается обратно в вариант.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. Аналогичным образом, тип переданного в вызов варианта может отличаться от типа варианта, возвращаемого из вызова.Again, the type of the variant passed into the call can differ from the type of the variant returned from the call.

Поведение по умолчанию при маршалинге варианта с установленным флагом VT_BYREFDefault behavior for marshaling a variant with the VT_BYREF flag set

  • Для варианта, передаваемого в управляемый код по значению, может быть установлен флаг VT_BYREF, который указывает, что вариант содержит ссылку вместо значения.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 this case, the variant is still marshaled to an object because the variant is being passed by value. Маршалер автоматически разыменовывает содержимое варианта и копирует его во вновь созданный объект до того, как будет выполнен вызов.The marshaler automatically dereferences the contents of the variant and copies it into a newly created object before making the call. После этого объект передается в управляемую функцию. Тем не менее при возврате из вызова объект не применяется к исходному варианту.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. Изменения, внесенные в управляемый объект, утрачиваются.Changes made to the managed object are lost.

    Внимание!

    Изменить значение варианта, переданного по значению, нельзя, даже если для варианта установлен флаг VT_BYREF.There is no way to change the value of a variant passed by value, even if the variant has the VT_BYREF flag set.

  • Для варианта, передаваемого в управляемый код по ссылке, также может быть установлен флаг VT_BYREF, который указывает, что вариант содержит еще одну ссылку.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. В этом случае вариант маршалируется в объект ref, поскольку вариант передается по ссылке.If it does, the variant is marshaled to a ref object because the variant is being passed by reference. Маршалер автоматически разыменовывает содержимое варианта и копирует его во вновь созданный объект до того, как будет выполнен вызов.The marshaler automatically dereferences the contents of the variant and copies it into a newly created object before making the call. При возврате из вызова значение объекта возвращается по ссылке с исходным вариантом только в том случае, если тип объекта совпадает с типом переданного объекта.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. Таким образом, при передаче не изменяется тип варианта с установленным флагом VT_BYREF.That is, propagation does not change the type of a variant with the VT_BYREF flag set. Если во время вызова тип объекта изменяется, при возврате из него возникает исключение InvalidCastException.If the type of the object is changed during the call, an InvalidCastException occurs on return from the call.

В следующей таблице описываются общие правила распространения для вариантов и объектов.The following table summarizes the propagation rules for variants and objects.

Исходный типFrom КомуTo Возвращаемые измененияChanges propagated back
Вариант vVariant v Объект oObject o НикогдаNever
Объект oObject o Вариант vVariant v НикогдаNever
Вариант * pvVariant * pv Ссылочный объект oRef Object o ВсегдаAlways
Ссылочный объект oRef object o Вариант * pvVariant * pv ВсегдаAlways
Вариант v (VT_BYREF | VT_*)Variant v (VT_BYREF | VT_*) Объект oObject o НикогдаNever
Вариант v (VT_BYREF | VT_)Variant v (VT_BYREF | VT_) Ссылочный объект oRef Object o Только если тип не был изменен.Only if the type has not changed.

См. такжеSee also