Background and Motivation
We wanted to quickly set attribute-tagged fields in user defined types at runtime. The fastest and most flexible way to do this would be various Unsafe APIs like AddByteOffset and As to get refs to the field and to then set them (obviously caching the field offsets ahead of time). The problem is that it's kind of extremely annoying to get the actual offset of individual fields: the best way I could figure out is using DynamicMethod to generate a tiny method that returns a ref to the field or the offset directly (because there is no FieldInfo.GetValueRef or something), then to Unsafe.ByteOffset<T> it.
So I simply propose an API that gets the in-memory offset of a field from the object's memory layout.
Proposed API
namespace System.Runtime.CompilerServices
{
public class Unsafe
{
public int OffsetOf<T>(string fieldName);
public int OffsetOf(Type t, string fieldName);
public int OffsetOf(FieldInfo field);
}
}
Usage Example
private static void SetField<T>(object o, int offset, T value)
{
// or some better way to get a base ref to the class, see below in "nuisances".
var asDummy = Unsafe.As<FieldOffsetDummy>(o);
ref var @ref = ref Unsafe.Add(ref asDummy.A, offset);
ref var oRef = ref Unsafe.As<byte, T>(ref @ref);
oRef = value;
}
private sealed class FieldOffsetDummy
{
public byte A;
}
var offset = Unsafe.OffsetOf(typeof(Foo), "Bar");
var foo = new Foo();
SetField(foo, offset, "hello");
Some nuisances
There isn't really a "clean" way to get a base reference this field offset can be used with. You can define a new class with a single byte field and then get a ref to that (after Unsafe.As) but that's far from clear or obvious.
So maybe an API to actually fetch the base reference for an object would go along with this aswell.
Background and Motivation
We wanted to quickly set attribute-tagged fields in user defined types at runtime. The fastest and most flexible way to do this would be various
UnsafeAPIs likeAddByteOffsetandAsto getrefs to the field and to then set them (obviously caching the field offsets ahead of time). The problem is that it's kind of extremely annoying to get the actual offset of individual fields: the best way I could figure out is usingDynamicMethodto generate a tiny method that returns arefto the field or the offset directly (because there is noFieldInfo.GetValueRefor something), then toUnsafe.ByteOffset<T>it.So I simply propose an API that gets the in-memory offset of a field from the object's memory layout.
Proposed API
Usage Example
Some nuisances
There isn't really a "clean" way to get a base reference this field offset can be used with. You can define a new class with a single
bytefield and then get a ref to that (afterUnsafe.As) but that's far from clear or obvious.So maybe an API to actually fetch the base reference for an object would go along with this aswell.