Skip to content

Proposal: RuntimeHelpers.GetRawData #28001

@MichalStrehovsky

Description

@MichalStrehovsky

Proposal

I suggest we add the following method to System.Runtime.CompilerServices.RuntimeHelpers:

namespace System.Runtime.CompilerServices
{
    public static class RuntimeHelpers
    {
        public static ref byte GetRawData(object o);
    }
}

Given an object instance o, this would return a managed reference to the first field of the type (or first element of an array if o is an array, or first character of a string if o is string). This can be implemented the same way JitHelpers.GetPinningHelper is implemented within the CLR and would have similar use.

Alternatives considered

We could place the helper in System.Runtime.CompilerServices.Unsafe, but that would be troublesome for variable-length types (arrays and string). If we ever add new ones (such as the Utf8string prototype), the API might not do what the user expects. This API needs to be versioned with the underlying runtime.

Example Usage

Create a strongly typed reflection-free field getter and setter:

abstract class FastFieldAccessor
{
    public abstract object GetValue(object o);
    public abstract void SetValue(object o);
}

class FastFieldAccessor<T> : FastFieldAccessor
{
    private IntPtr _offset;

    public FastFieldAccessor(object o, ref T field)
    {
        _offset = Unsafe.ByteOffset(ref RuntimeHelpers.GetRawData(o), ref Unsafe.As<T, byte>(ref field));
    }

    public override object GetValue(object o)
    {
        return Unsafe.As<byte, T>(ref Unsafe.Add(ref RuntimeHelpers.GetRawData(o), _offset));
    }

    public override void SetValue(object o)
    {
        Unsafe.As<byte, T>(ref Unsafe.Add(ref RuntimeHelpers.GetRawData(o), _offset)) = (T)o;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions