这个问题是关于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 });
}
当在Mac上的Unity编辑器中运行时,它会按照预期工作。在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条答案
按热度按时间mutmk8jj1#
是的,因为IL 2CPP是一个超前(AOT)编译器,它只适用于编译时存在的代码。这里没有代码在“真实的的”C#源代码中使用
GenericMethod<float>
,所以IL 2CPP不知道生成相应的代码来使该实现工作。这里真实的的限制是泛型参数类型是
float
,这是一种值类型。在这种情况下,您可以使用string
(一种引用类型),没有任何问题。IL 2CPP共享所有泛型类型的实现,这些泛型类型具有泛型参数,该泛型参数是引用类型(例如string
、object
等)。这是可能的,因为C#中的所有引用类型都是相同的大小(IntrPtr.Size
,确切地说)。所以这里的限制实际上是双重的:
1.此限制仅适用于类型参数为值类型时的泛型类型。
请注意,IL 2CPP理论上也可以使用值类型泛型参数共享泛型类型的实现,尽管这还没有实现。
编辑:从Unity 2022.2开始,这已经实现了-
ExecutionEngineException
将不再发生,并且原始场景将工作。