2

I have the following generic type with a generic type constraint.

public class GenericType<T> where T: IFoo
{
}

Then I try to create a closed generic type from the open generic type.

var fooGenericType = typeof(GenericType<>).MakeGenericType (typeof(IFoo));  
var intGenericType = typeof(GenericType<>).MakeGenericType (typeof(int)); 

When running in the simulator it fails on trying to create a closed generic type using an int as the type parameter which is expected.

BUT, when running on the actual device (iPhone), it will also create a closed generic type using an int. It seems like it does not respect the generic constraint, but this happens only on the device. On the simulator everything is as expected.

Any ideas?

der_michael
  • 3,151
  • 1
  • 24
  • 43
seesharper
  • 3,249
  • 1
  • 19
  • 23

2 Answers2

2

This seems to be related to the fact that MonoTouch uses AoT compilation. It causes some limitations regarding generic types, as pointed here

William Barbosa
  • 4,936
  • 2
  • 19
  • 37
  • I am aware of the documentation with regards to generics and its limitations. This however, does not seem like a limitation as it acts more forgiving on the device as opposed to when running in the simulator. It is pretty remarkable that it is possible to create any of the closed generic types based on the limitations regarding generic types. Is there any kind of fallback mechanism here, like the type erasure stuff going on in Java? – seesharper Aug 24 '15 at 15:02
  • It's not that the emulator is more forgiving. The emulator is not running [full AOT](http://stackoverflow.com/a/16779056/3465182), whereas the device is. – William Barbosa Aug 24 '15 at 18:39
  • I understand that the device is running full AOT. With all due respect I think you might misunderstood my question. Just to clearify This "works" on the simulator in the sense that id does throw an exception because of the generic constraint. var intGenericType = typeof(GenericType<>).MakeGenericType (typeof(int)); If I run exactly the same code on the actual device it will wrongfully create a closed generic type using the int type parameter completely ignoring the constraint. – seesharper Aug 24 '15 at 19:38
  • It's indeed ignoring the constraint because an iPhone has no means to check it during runtime. The emulator throws the exception because the CLR is checking the type constraints in runtime. This is the JIT doing its magic. It just can't happen in an AOT compilation. Hence why this is a limitation. – William Barbosa Aug 24 '15 at 19:53
  • That's good enough for me, William. Thanks for the clarification. I am a little surprised though that anything that uses MakeGenericType can work on iOS since the types are not known at compile time. Do you know how this works internally on the phone. Are these types backed by system.object or something similar? – seesharper Aug 24 '15 at 20:03
0

Like William Barbosa mentioned there are limitations regarding generic types on iOS. The linker excludes combinations of generic types with several parameters when it thinks they are not necassary. As the simulator is a different build target the linker might work differently.

You can force the linker to include a generic type with specific type parameters by using them anywhere in your code. A common way is to provide a LinkerPleaseInclude.cs file like here: https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/DailyDilbert/DailyDilbert.Touch/LinkerPleaseInclude.cs

It's also pointed out here: MakeGenericMethod/MakeGenericType on Xamarin.iOS

Community
  • 1
  • 1
Wosi
  • 41,986
  • 17
  • 75
  • 82
  • 1
    The question is not really why is does not work, but rather why it works. My linker option on the device is set to "SDK assemblies only" and still it is possible to create a closed generic type that is not known at compile time. How can that be? And more importantly, why does it allow creation of an invalid closed generic type that does not comply to the generic constraint? My suspicion here is that the xamarin "compiler" does its best to hide these errors (maybe treating these unknown types as object) and in this case, gets it kind of wrong. – seesharper Aug 24 '15 at 16:18