Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Getting sizeof(T) where T : struct Possible #3208

Closed
whoisj opened this issue Jun 1, 2015 · 7 comments
Closed

Make Getting sizeof(T) where T : struct Possible #3208

whoisj opened this issue Jun 1, 2015 · 7 comments

Comments

@whoisj
Copy link

whoisj commented Jun 1, 2015

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

@whoisj
Copy link
Author

whoisj commented Jun 2, 2015

Updated based on the conversation happening in #3210

@damageboy
Copy link

@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...)

@whoisj
Copy link
Author

whoisj commented Apr 14, 2016

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));
    }

@axel-habermaier
Copy link
Contributor

axel-habermaier commented Apr 15, 2016

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#.

@ghord
Copy link

ghord commented Aug 25, 2016

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..
    }

@jcouv
Copy link
Member

jcouv commented Oct 22, 2017

Moving language design discussion to csharplang. Thanks

@jcouv jcouv closed this as completed Oct 22, 2017
@jcouv
Copy link
Member

jcouv commented Oct 22, 2017

Issue moved to dotnet/csharplang #1032 via ZenHub

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants