Этот вопрос конкретно о Unity3d IL2CPP и iOS.
Вызов универсального метода с использованием отражения
class SourceValue<T> { public T value; }
class TargetValue<T> { public T value; }
static TargetValue<T> GenericMethod<T> (SourceValue<T> source) {
return new TargetValue<T> { value = source.value };
}
void Main () {
Type genericType = typeof(SourceValue<float>);
Type typeArg = genericType.GenericTypeArguments[0];
MethodInfo mi = GetType ().GetMethod ("GenericMethod", Flags | BindingFlags.Static);
MethodInfo gmi = mi.MakeGenericMethod (typeArg);
object src = new SourceValue<float> { value = 0.5f };
object trg = gmi.Invoke (this, new object[] { src });
}
Это работает, как и ожидалось, при запуске в редакторе Unity на Mac. Вызывает сбой на iOS с ошибкой:
ExecutionEngineException: Attempting to call method 'GenericMethod<System.Single>' for which no ahead of time (AOT) code was generated.
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0
Просто система AOT не может вызывать универсальные методы или я что-то упустил?
Всего 1 ответ
Да, поскольку IL2CPP является компилятором с опережением времени (AOT), он работает только для кода, который существует во время компиляции. Никакой код здесь не использует GenericMethod<float>
в «реальном» исходном коде C #, поэтому IL2CPP не знает, как сгенерировать соответствующий код, чтобы эта реализация работала.
Реальное ограничение здесь заключается в том, что универсальным типом аргумента является float
, который является типом значения. Вы можете использовать string
(ссылочный тип) в этом случае без каких-либо проблем. IL2CPP разделяет реализацию всех универсальных типов, которые имеют универсальный аргумент, который является ссылочным типом (например, string
, object
и т. Д.). Это возможно, потому что все ссылочные типы в C # имеют одинаковый размер ( IntrPtr.Size
, IntrPtr.Size
).
Таким образом, ограничение здесь действительно двоякое:
Обратите внимание, что теоретически IL2CPP также может совместно использовать реализацию универсальных типов с универсальными аргументами типа значения, хотя это еще не было реализовано.