Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
Mono organizations on
GitHub to continue tracking issues. Bugzilla will remain
available for reference in read-only mode. We will continue to work
on open Bugzilla bugs, copy them to the new locations
as needed for follow-up, and add the new items under Related
Our sincere thanks to everyone who has contributed on this bug
tracker over the years. Thanks also for your understanding as we
make these adjustments and improvements for the future.
Please create a new report on
GitHub or Developer Community with
your current version information, steps to reproduce, and relevant error
messages or log files if you are hitting an issue that looks similar to
this resolved bug and you do not yet see a matching new report.
Found: A recent alpha channel update (this week?) resulted in breakage of previously functioning code of the form:
public static unsafe void Foo<T>(T data) where T : struct
fixed (T* t = &data)
// Do stuff.
The pattern above now results in "Cannot take the address of, get the size of, or declare a pointer to a managed type T" errors, which you would normally see had the T not been qualified with the "where T : struct" portion.
Expected: So long as a T is qualified as struct (value type), the above pattern continues to work.
NOTE: The non-generic cases still work as expected. E.g., the following results in the same error indicated above:
public class MyType
public static unsafe void Foo(MyType data)
fixed (MyType* t = &data)
// Do stuff.
...yet the above block does *not* result in an error if the class is changed to a struct.
This appears to have been a recent change to the behavior of generics, has the symptom that the "where T : struct" is no longer being honored?
Unfortunately, we are having to specialize our previously-functioning generics all over the codebase (much duplication) in order to be able to continue to compile/run in this condition.
Forgot to add:
Version 4.1.11 (build 10)
Installation UUID: b577b744-52dd-4f14-848b-8dcc8a961c91
Mono 3.2.3 ((no/8d3b4b7)
The code violates C# spec so the error is correct.
It depends what you need to achieve but you can use something like this instead
var handle = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr address = handle.AddrOfPinnedObject();
// free handle later
Thanks for the quick response, Marek.
I'll take a look at the spec a little closer. I installed a copy of MSVS (had been using Xamarin Studio exclusively to date) and found the same results.
It remains an academic curiosity to me why, though, the spec (or at least the current compilers) would allow fixed blocks to acquire pointers to arrays of concrete structs, while at the same time disallow the same in the generic case even if the Ts are constrained to structs. You are, in essence, telling the compiler that the type is constrained to that which it *would* allow had you simply typed it concretely yourself. Generics are supposed to help us reduce that typing.
If I am missing something you can shed light on (e.g. a struct case that would be illegal that the generic has to protect against), I'd love to hear it. (But don't go out of your way, just curious.)
I will look into the alternatives.
Just a quick followup/conclusion. Indeed, the generic case qualified as struct does not fully guarantee a legal struct, as all struct members must also be of unmanaged types. Thus compilers have to disallow the pattern.