I took often find myself writing long lists of methods (like below) where I'm reading the bits of stack values for things like hashing, serialization, encryption, etc. because I'm unable to acquire sizeof(T)
even when T : struct
which I I find fairly frustrating.
public unsafe void Write(DateTime value)
{
lock (_buffer)
{
fixed (byte* b = _buffer)
{
*((DateTime*)b) = value;
}
Write(_buffer, 0, sizeof(DateTime));
}
}
Ideally the sizeof(...)
operator would work on generics so long as the type being measured is guaranteed to be a value type (ala struct).
This should be perfectly legal code:
public unsafe void Write<T>(T value)
where T : blittable struct
{
lock (_buffer)
{
fixed (byte* b = _buffer)
{
*((T*)b) = value;
}
Write(_buffer, 0, sizeof(T));
}
}
Then I would only need a single method and not a dozen.
Support for T*
is #3210
Updated based on the conversation happening in #3210
@whoisj while I would obviously agree with you that this is very handy and should be supported directly in c#, isn't something along the lines of http://stackoverflow.com/questions/18167216/size-of-generic-structure a temporary workaround for you? (With very little performance overhead...)
The solution presented on SO seems reasonable, but I'm not certain about the runtime costs associated with passing value through the marshaler to get its size. Still, it seems to me to be a work-around for a missing feature, especially when the underlying IL supports the operation and it is C# which imposes the limitation.
public static int SizeOf<T>() where T : struct
{
return Marshal.SizeOf(default(T));
}
There is also DotNetCross.Memory.Unsafe that exposes some IL instructions as regular .NET methods that are unavailable in C#. The library is implemented using IL instead of C#. For instance:
var size = Unsafe.SizeOf<T>();
In my opinion, however, most of the stuff exposed by the library should be available directly in C#.
blittable
constraint is such a nice way to solve most of the issues with generic pointers, yet everyone keeps insisting on using hacks like Unsafe.Size<T>()
. Just look how clean following code is:
public unsafe class NativeArray<T> where T : blittable
{
IntPtr ptr_;
public NativeArray(int size)
{
ptr_ = Marshal.AllocHGlobal(size * sizeof(T));
}
public T* this[int i]
{
get { return ((T*)ptr_) + i; }
}
public int ElementSize => sizeof(T);
//finalizers etc..
}
Moving language design discussion to csharplang. Thanks
Issue moved to dotnet/csharplang #1032 via ZenHub
Most helpful comment
blittable
constraint is such a nice way to solve most of the issues with generic pointers, yet everyone keeps insisting on using hacks likeUnsafe.Size<T>()
. Just look how clean following code is: