Unity中C# Activator.CreateInstance传参误调无参构造解决方法
问题根因
这是C#重载决议规则和Unity引擎特殊设计叠加踩的坑:
Activator.CreateInstance有两个高频使用的重载:CreateInstance(Type type, bool nonPublic):第二个参数为布尔值,作用是控制是否允许调用非公有构造函数,这个重载只会调用目标类型的无参构造。CreateInstance(Type type, params object[] args):第二个参数是变长参数数组,用来传入构造函数所需的入参,内部会自动匹配参数签名对应的构造函数执行。
- 所有继承自
UnityEngine.Object的类型(包括你定义的HexMap),Unity都为其实现了隐式转bool的运算符,用来快速判断对象是否为有效实例。 - 你写的
Activator.CreateInstance(typeof(B), hexMap),在编译阶段做重载决议时,编译器会优先选择参数匹配度更高的重载:HexMap可以隐式转换为bool,这个转换的优先级远高于将单个对象包装为params object[]数组的优先级,所以最终实际调用的是带bool参数的重载,自然只会执行B的无参构造函数,你传入的hexMap参数根本没被用到构造逻辑里。
解决方案
核心是让编译器明确匹配到带object[]入参的重载,或者直接绕开Activator的自动匹配逻辑,两种写法都可以:
方案1:显式传入object数组(改动最小)
把参数显式包装为object数组,编译器就不会误匹配到bool参数的重载,直接走带构造参数的逻辑:
HexMap hexMap = Object.FindObjectOfType<HexMap>(); A a = (A)Activator.CreateInstance(typeof(B), new object[] { hexMap });
这个写法只需要修改传参格式,改动成本最低,执行时会正确匹配到B类带HexMap参数的构造函数。
方案2:显式反射获取目标构造函数调用(稳定性最高)
如果想彻底规避重载决议、自动参数匹配带来的不确定问题,可以直接通过反射拿到需要的构造函数再调用,适合生产环境使用:
HexMap hexMap = Object.FindObjectOfType<HexMap>(); // 明确查找入参签名为HexMap的公有构造函数 ConstructorInfo ctor = typeof(B).GetConstructor(new Type[] { typeof(HexMap) }); A a = (A)ctor.Invoke(new object[] { hexMap });
这种写法完全绕开了Activator的内部匹配逻辑,不会因为Unity的特殊运算符设计、隐式转换问题出现异常。
内容的提问来源于stack exchange,提问作者Sergey Miroshnichenko
相关产品推荐
相关产品推荐

