Repository: dotnet/runtime
File: src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs (C#)

Code before:

        // Pointer to MngdNativeArrayMarshaler, ownership not assumed.
        private readonly IntPtr pvArrayMarshaler;

        // Type of action to perform after the CLR-to-unmanaged call.
        private BackPropAction backPropAction;

        // The managed layout type for BackPropAction.Layout.
        private Type? layoutType;

        // Cleanup list to be destroyed when clearing the native view (for layouts with SafeHandles).
        private CleanupWorkListElement? cleanupWorkList;

        [Flags]
        internal enum AsAnyFlags
        {
            In = 0x10000000,
            Out = 0x20000000,
            IsAnsi = 0x00FF0000,
            IsThrowOn = 0x0000FF00,
            IsBestFit = 0x000000FF
        }

        private static bool IsIn(int dwFlags) => (dwFlags & (int)AsAnyFlags.In) != 0;
        private static bool IsOut(int dwFlags) => (dwFlags & (int)AsAnyFlags.Out) != 0;
        private static bool IsAnsi(int dwFlags) => (dwFlags & (int)AsAnyFlags.IsAnsi) != 0;
        private static bool IsThrowOn(int dwFlags) => (dwFlags & (int)AsAnyFlags.IsThrowOn) != 0;
        private static bool IsBestFit(int dwFlags) => (dwFlags & (int)AsAnyFlags.IsBestFit) != 0;

        internal AsAnyMarshaler(IntPtr pvArrayMarshaler)
        {
            // we need this in case the value being marshaled turns out to be array
            Debug.Assert(pvArrayMarshaler != IntPtr.Zero, "pvArrayMarshaler must not be null");

            this.pvArrayMarshaler = pvArrayMarshaler;
            backPropAction = BackPropAction.None;
            layoutType = null;
            cleanupWorkList = null;
        }

        #region ConvertToNative helpers

        private unsafe IntPtr ConvertArrayToNative(object pManagedHome, int dwFlags)
        {
            Type elementType = pManagedHome.GetType().GetElementType()!;
            VarEnum vt;

            switch (Type.GetTypeCode(elementType))
            {
                case TypeCode.SByte: vt = VarEnum.VT_I1; break;
                case TypeCode.Byte: vt = VarEnum.VT_UI1; break;

Review comment (bug):
The parameter name has been changed from `pNativeHome` to `_` (discard). However, this changes the parameter name in a non-UnmanagedCallersOnly method that may be called from other locations. This could affect debugging and stack traces. Consider keeping the original parameter name for consistency with the other methods in this class.
```suggestion
        internal static void ClearManaged(ICustomMarshaler marshaler, in object pManagedHome, IntPtr* pNativeHome)
```

Code after:
            }

            try
            {
                marshaler.CleanUpNativeData(*pNativeHome);
            }
            catch
            {
                // COMPAT: We need to swallow all exceptions thrown by CleanUpNativeData.
            }
        }

        [UnmanagedCallersOnly]
        internal static void ClearManaged(ICustomMarshaler* pMarshaler, object* pManagedHome, IntPtr* pNativeHome, Exception* pException)
        {
            try
            {
                ClearManaged(*pMarshaler, in *pManagedHome, pNativeHome);
            }
            catch (Exception ex)
            {
                *pException = ex;
            }
        }

        internal static void ClearManaged(ICustomMarshaler marshaler, in object pManagedHome, IntPtr* _)
        {
            // COMPAT: We never pass null to CleanUpManagedData.
            if (pManagedHome is null)
            {
                return;
            }

            marshaler.CleanUpManagedData(pManagedHome);
        }
    }  // class MngdRefCustomMarshaler

    internal struct AsAnyMarshaler
    {
        private const ushort VTHACK_ANSICHAR = 253;
        private const ushort VTHACK_WINBOOL = 254;

        private enum BackPropAction
        {
            None,
            Array,
            Layout,
            StringBuilderAnsi,
            StringBuilderUnicode
        }