Why does Marshal.SizeOf<T>()
require non-generic types, but Marshal.SizeOf<T>(T)
doesn't?
#96487
-
I wanted to use However, curiously, the overload that takes an object of type A simple example using nullable value types ( using System;
using System.Runtime.InteropServices;
Console.WriteLine(Marshal.SizeOf<int?>()); // throws `ArgumentException`
Console.WriteLine(Marhsal.SizeOf<int?>(42)); // prints "4" (not "8" as `sizeof(int?)` would, but ignore that)
Console.WriteLine(Marshal.SizeOf<int?>(new()); // ditto Is there a reason for this restriction? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Historically, generics were not supported in marshalling and so could not be passed across the P/Invoke boundary, this was changed around .NET Core 3.1, but many of the
runtime/src/coreclr/vm/mlinfo.cpp Lines 1084 to 1101 in 04afbf7 CC. @AaronRobinsonMSFT, @jkoritzinsky who may be able to provide additional context/info |
Beta Was this translation helpful? Give feedback.
-
I'm not sure about the limitation, but |
Beta Was this translation helpful? Give feedback.
Marshal.SizeOf<T>()
is intended to get the size of the object after it's been marshalled and so is effectively the number of bytes that native sees.sizeof(T)
(andUnsafe.SizeOf<T>()
is the size of the object in managed, which will match the size for blittable types.Historically, generics were not supported in marshalling and so could not be passed across the P/Invoke boundary, this was changed around .NET Core 3.1, but many of the
Marshal
APIs were not updated to account for that as the built-in marshalling was already being considered "legacy" and was being looked at getting replaced (see https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.disableruntimemarshal…