Every method parameter can be associated with a setting for the InAttribute attribute, the OutAttribute attribute, or both. You apply directional attributes at design time to modify run-time marshaling between managed and unmanaged memory.
InAttribute and OutAttribute are located in the System.Runtime.InteropServices namespace and are equivalent to the Interface Definition Language (IDL) interface attributes [in], [out], [in/out], and [out, retval].
Note The return value of a managed method signature always maps to [out, retval] in a type library. There is no equivalent directional attribute you can apply.
Directional attributes are optional. You apply them to method parameters when you want to alter the default behavior of the marshaler. If you omit directional attributes from a method parameter, the marshaler determines the directional flow based on the type of the parameter (value or reference) and its modifiers, if any.
Some languages provide keywords that enable you to modify the directional flow of method parameters. The following table lists the direction-related keywords provided by Visual Basic .NET and C# and shows the equivalent IDL interface attribute.
|Visual Basic .NET||C#||IDL attribute|
ByRef, ref, and out parameter modifiers cause method arguments to be marshaled by reference rather than by value. Method arguments passed by value are marshaled to unmanaged code as values on the stack; arguments passed by reference are marshaled as pointers on the stack. The following illustration shows the default marshaling behavior of value types and reference types with parameter modifiers.
Default marshaling of method arguments to unmanaged code
By default, reference types (classes, arrays, strings, and interfaces) passed by value are marshaled as In parameters for performance reasons. You do not see changes to these types unless you apply InAttribute and OutAttribute (or just OutAttribute) to the method parameter. The StringBuilder class, which is an exception to this rule, is marshaled as an In/Out parameter.
The interop marshaler guarantees the following behavior with regard to directional attributes:
- The interop marshaler never generates a write operation to an In parameter passed from unmanaged code. Thus, unmanaged code can safely pass a pointer to a read-only page, or a pointer to concurrently accessed data.
- When the copied object contains an allocated object, such as a BSTR, the marshaler always executes the correct sequence of allocations and destructions demanded by the In/Out settings.
It is important to apply directional attributes accurately in your code. Properly applying InAttribute and OutAttribute to parameters in managed code ensures that the Type Library Exporter (Tlbexp.exe) uses these bits to set the In/Out bits in the corresponding type library; this is particularly important for reference types that can be pinned, such as some arrays and classes.