Skip to main content

02-TYPE-SYSTEM

文档站副本

本页为语义契约的发布副本;请在上游 ZTSTest/Docs/spec 修改后执行 npm run sync-spec。(源:02-TYPE-SYSTEM.md

--- sidebar_position: 3 title: "类型系统"

02 — 类型系统

JS 侧访问 C# 类型、成员与构造 的规范。适用于 Il2Cpp(Player)Mono(Editor)。 脚本推荐 import { T } from "csharp:…"(§2.11);CSharp[assembly][typeFullName] 为权威低层路径。 成员属性分派metatable/ 参数 Marshal(Push/Pop)marshal/

平台原则: Il2Cpp 侧重零 GC 与 direct methodPointer;Mono 可反射 / Emit,但 JS 可见语义必须与 Il2Cpp 一致


1. 设计目标

目标说明
统一入口普通类型经 CSharp 根对象懒加载;脚本推荐 import { T } from "csharp:…"(§2.11),与 CSharp 解析到同一类型对象
语义贴近 C#Type.staticMethod()obj.instanceMethod()new Type(...)
静实例隔离静态与实例使用 独立 元数据与三表
仅 publicJS 仅可访问 public 成员
Bind 期扁平继承静/实例成员均在 EnsureBinding 写入当前类型三表;运行时沿继承链查找
属性 miss读/写未注册成员 → throw Error('zts: …')(见 metatable/02-INDEX.md
方法 thisobj.Method(args) 作为 方法调用 时自动传入 CLR this;提取函数 自动绑定

2. 类型命名与解析

2.1 CSharp 根对象

CSharp -- 全局对象,属性 miss → 懒加载程序集
└─ {assemblyName} -- 程序集对象
└─ {typeFullName} -- 类型对象(§3)

程序集名为简单名(不含 .dll),如 Assembly-CSharpmscorlib

CSharp.AC = CSharp['Assembly-CSharp']; // 可选别名

脚本侧 推荐 使用 import { T } from "csharp:…"(§2.11),不必经过全局 CSharpCSharp 仍是权威低层入口(调试、嵌套类型、adaptor)。

2.2 类型访问语法

无命名空间(全局命名空间)

合法标识符时可用点号:

CSharp.AC.Demo
CSharp['Assembly-CSharp'].Demo

含命名空间(强制括号)

禁止 CSharp.AC.MyGame.UI.Panel;须整段 typeFullName 为键:

CSharp.AC['MyGame.UI.Panel']
CSharp['Assembly-CSharp']['MyGame.UI.Panel']

规则: namespace 中的 . 属于 字符串键,不是 JS 对象路径。

程序集名含特殊字符

CSharp['Assembly-CSharp']['MyGame.UI.Panel']
场景写法
无 namespace + 合法标识符CSharp.{asm}.{TypeName}
有 namespaceCSharp.{asm}['Ns.Type'] 必须
嵌套类型CSharp.{asm}['Outer+Inner'] 必须+ 分隔)
-+`对应段用 ['...']

2.3 命名空间与嵌套类型

  • 命名空间: MyGame.UI.Panel → namespace MyGame.UI,类名 Panel
  • 嵌套类型: {OuterFullName}+{NestedClassName},与 Type.FullName 一致
CSharp.AC['TopClass+NestedClass']
CSharp.AC['MyGame.UI.Outer+Inner']

// 禁止用 '.' 连接嵌套层:
// CSharp.AC['Outer.Inner'] ✗

类型对象内部槽 [[FullName]] 存上述字符串;native 不做 .+ 转换。

2.4 类型实参(typeArg)

用于 zts.make_generic_typemake_szarray_type 等(见 05-LIB.md)。

形式说明
CSharp[assembly][typeFullName]csharp: named export类型对象(二者 identity 相同,§2.11)
zts.make_generic_type / make_szarray_type / make_mdarray_type 返回值intern 类型对象
mscorlib 字符串"System.Int32" corlib
zts.types.*mscorlib 全名常量

禁止: 任意普通 JS object、非 ZTS exotic object、zts.typeof(...) 返回值作为 make_*_type 的 typeArg(typeof 供签名等,见 §2.7)。

2.5 泛型类型

const ListDef = CSharp.mscorlib['System.Collections.Generic.List`1'];
const List_int = zts.make_generic_type(ListDef, zts.types.int32);

const Dict_str_int = zts.make_generic_type(
CSharp.mscorlib['System.Collections.Generic.Dictionary`2'],
zts.types.string,
zts.types.int32
);
  • genericBaseType:未闭合定义(含 ` 与 arity)
  • 实参个数须与 arity 一致;相同实参 intern 同一类型对象

2.6 数组类型

const int_arr = zts.make_szarray_type(zts.types.int32); // int[]
const md_type = zts.make_mdarray_type(zts.types.int32, 2); // int[,]

rank ≥ 1;szarray 与 mdarray 为不同类型。

2.7 zts.typeof

// 等价于 C# typeof(Demo) / typeof(List<int>)
const t = zts.typeof(CSharp.AC.Demo);
const ListInt = zts.make_generic_type(
CSharp.mscorlib['System.Collections.Generic.List`1'],
zts.types.int32
);
const t2 = zts.typeof(ListInt); // 闭合泛型 / 数组等任意类型对象均可

typeObject任意 ZTS 类型对象。返回值 为该类型的 System.Type 反射对象(class exotic object),语义对应 C# typeof(T)。可供需要 System.Type 的 API / 签名场景使用;作为 §2.4 typeArg。

2.8 zts.types / zts.get_type_from_name

05-LIB.md §4.2、§4.3。get_type_from_name(typeFullName) 对标 System.Type.GetType(string),返回类型对象(支持 AQN、泛型、数组)。

2.9 类型获取途径

途径适用示例
CSharp[assembly][typeFullName]class、struct、enum、delegate、interface、嵌套、未闭合泛型定义CSharp.AC['Outer+Inner']
import { T } from "csharp:…"同上(按程序集 + 命名空间 / 声明类型);见 §2.11import { Panel } from "csharp:Assembly-CSharp/MyGame.UI"
zts.get_type_from_name单字符串解析(AQN / 泛型 / 数组)zts.get_type_from_name("System.Int32[]")
zts.make_generic_type闭合泛型List<int>
zts.make_szarray_typeT[]
zts.make_mdarray_typeT[,…]

CSharp[...]csharp: 模块直接解析:闭合泛型、数组类型(须 make_*get_type_from_name)。

懒加载

CSharp[assemblyName] 属性 miss → 创建程序集对象 → 缓存

assembly[typeFullName] 属性 miss → 解析 Type → EnsureBinding → 缓存
miss行为
程序集不存在throw Error('zts: assembly not found: {assemblyName}')
类型不存在throw Error('zts: type not found: {typeFullName}')

禁止对不存在的程序集 / 类型返回 undefined

EnsureCSharpRoot 仅在启动时一次;之后 C# 侧取得全局 CSharp 根对象。

2.10 类型对象元数据(解析用)

下列为 脚本可读调试可见 的约定字段(实现可通过 Symbol 或不可枚举属性暴露;键名以 TsConsts 为准):

字段说明
__typeid闭合泛型 / 数组等反查 id
__assembly程序集简单名
__fullname§2.3 规范全名
__name短名
__structstruct:true
__enumenum:true
__nullableNullable<T> 闭合类型:true
__byvalInstanceProtostruct 的 ByVal 实例分派原型;Nullable
__byobjInstanceProtoByObj 实例分派原型
__klassnative:Il2CppClass* / Mono typeId

2.11 csharp: 虚拟模块(推荐脚本写法)

权威解析仍是 CSharp[assembly][typeFullName](§2.1–§2.9)。本节是与之 identity 等价 的 ES import 语法,不改变 EnsureBinding、三表或 miss 语义。 Loader 约定见 01-HOST-API.md §1.3;不是 12-MIGRATION-ADAPTORS.mdCS.* 全局链。

脚本推荐:

import { MyClass } from "csharp:Assembly-CSharp/foo";
import { Panel } from "csharp:Assembly-CSharp/MyGame.UI";
import { GameObject } from "csharp:UnityEngine.CoreModule/UnityEngine";
import { Demo } from "csharp:Assembly-CSharp"; // 无命名空间

const panel = new Panel();

对应关系:

import等价核心路径
{ MyClass } from "csharp:Assembly-CSharp/foo"CSharp['Assembly-CSharp']['foo.MyClass']
{ Panel } from "csharp:Assembly-CSharp/MyGame.UI"CSharp['Assembly-CSharp']['MyGame.UI.Panel']
{ Demo } from "csharp:Assembly-CSharp"CSharp['Assembly-CSharp'].Demo(全局命名空间)

2.11.1 Specifier 文法

csharp-specifier := "csharp:" assembly [ "/" ns-or-decl ]
assembly := CLR 程序集简单名(不含 `.dll`;可含 `.` 与 `-`,如 `UnityEngine.CoreModule`、`Assembly-CSharp`)
ns-or-decl := CLR 命名空间(可含 `.`)
| 声明类型的 `typeFullName`(嵌套用 `+`)
| 声明类型 `typeFullName` 后接字面量 `+`(强制嵌套模块,见 §2.11.3)
规则说明
前缀必须csharp:(保留 scheme)。禁止"Assembly-CSharp" 以免与业务 moduleLoader specifier 冲突
第一个 /分隔 程序集路径;程序集名不得含 /
第二个及以后 /非法throw Error('zts: invalid csharp module specifier: …')(命名空间用 .,不用再切路径段)
// 后为空该程序集 全局命名空间Type.Namespace 为空)
绝对 specifiercsharp: 开头 原样 作为模块名;module_normalize 不得 按相对路径改写
大小写CSharp 根对象相同(CLR 简单名 / 命名空间)

非法示例:csharp:csharp:/foocsharp:asm/MyGame/UIcsharp:asm/../x

2.11.2 模块种类与 named export

每个合法 specifier 对应 一个 合成 ES 模块(无 JS 源码;由 loader 创建 C module 或等价物)。 default export。

命名空间模块(路径不含强制嵌套后缀 +,且按 §2.11.3 判定为命名空间):

  • 导出该程序集中、DeclaringType == null、且 Type.Namespace 等于该路径(全局命名空间则为空)的 public 类型。
  • named export 名为 §2.11.4 的 导出名(通常为 CLR 短名)。
  • 导出:嵌套类型、闭合泛型、数组类型、无法编码为合法 JS IdentifierName 的名字(仍可用 CSharp[...])。

声明类型模块(嵌套模块,§2.11.3):

  • 导出该声明类型的 直接 public 嵌套类型(一层;更深嵌套再以其 typeFullName 打开模块)。

同一模块内导出名冲突(编码后相同)→ 模块实例化失败:throw Error('zts: csharp export name conflict: {name} in {specifier}')

2.11.3 命名空间 vs 嵌套类型

C# 允许 namespace Foo.Bar 与类型 Foo.Bar 并存。解析路径 P(不含末尾强制 +)时:

条件模块种类
P 为空全局命名空间模块
存在 public 非嵌套类型,其 Namespace == P命名空间模块(即使同时存在全名为 P 的类型)
否则,且程序集中存在 typeFullName == P 的类型声明类型模块(导出其直接嵌套类型)
否则空模块(无 named export;程序集必须存在)

强制声明类型模块:路径以字面量 + 结尾(P = 去掉末尾 + 后的 typeFullName)。用于「命名空间 P 与类型 P 并存」时导入该类型的嵌套类型。

import { Baz } from "csharp:Assembly-CSharp/Foo.Bar"; // 命名空间 Foo.Bar 中的 Baz
import { Inner } from "csharp:Assembly-CSharp/Foo.Bar+"; // 类型 Foo.Bar 的嵌套 Inner
import { Deep } from "csharp:Assembly-CSharp/Foo.Bar+Inner+"; // 更深一层

禁止把嵌套类型挂到外层类型对象的自有属性上(避免与静态成员撞名)。嵌套类型 经声明类型模块的 named export 或 CSharp[asm]['Outer+Inner'] 取得。

2.11.4 导出名编码

CLR 短名named export说明
PanelDemoPanelDemo合法标识符原样
List`1List$1`$
Dictionary`2Dictionary$2同上
嵌套 InnerInner由声明类型模块导出,不是 Outer+Inner

无 arity 糖: 去掉 `$N` 后缀后的名字在该模块内不与其它 export 冲突,则 额外 导出该短名,且与带 $N 的 export 同一类型对象

import { List, List$1 } from "csharp:mscorlib/System.Collections.Generic";
console.assert(List === List$1);
const ListInt = zts.make_generic_type(List, zts.types.int32);

同命名空间同时存在 FooFoo`1导出无 arity 的糖名;Foo`1Foo$1Foo 仍指向非泛型类型。

开放泛型的 构造 仍走 zts.make_generic_type(§2.5);csharp: 只提供类型定义对象。

2.11.5 Identity、惰性与 miss

规范
Identityimport { T } 得到的对象 必须CSharp[assembly][typeFullName] 同一引用
成员绑定EnsureBinding 急切度 不得高于 取得该类型对象的 CSharp[...] 路径
同模块其它类型静态 import { Panel } 物化 Panel禁止 因打开该命名空间模块而对未 import 的类型做 EnsureBinding
CSharp 上 missthrow(§2.9)
csharp: 未导出的静态 import遵循 普通 ES 模块 链接失败(名字不在 export 列表)
import * as ns; ns.Missing标准模块命名空间 → undefined不是 CSharp 的 miss throw)

程序集不存在 → throw Error('zts: assembly not found: {assemblyName}')(与 CSharp 相同),不得 交给宿主 moduleLoader

声明类型模块的 typeFullName 不存在 → throw Error('zts: type not found: {typeFullName}')

2.11.6 Loader 与 GetFunction

csharp: 由 ZTS 运行时 在宿主 moduleLoader 之前 拦截并合成模块,不得csharp: specifier 传给业务 loader。与第三方原生 C 模块的优先级见 build/05-NATIVE-MODULES.mdcsharp: 为 ZTS 保留,禁止 第三方以同一前缀注册。

csharp: 模块的 named export 是 类型对象,一般 不是 业务 callable。GetFunction<T>(jsModule, jsExportName) 不应csharp: specifier 作为脚本入口;若误用,按现有规则因「非 callable」抛 C# 异常。

合成模块 源码、 相对 import;业务模块用绝对 "csharp:…" 引用。声明文件如何生成见 14-TYPESCRIPT.md §6。

2.11.7 非目标(本节明确不做)

说明
整程序集短名摊平foo.MyClassbar.MyClass 都导出为 csharp:asm 上的 MyClass(短名只在同一命名空间 / 同一声明类型内唯一)
命名空间对象链 提供官方 CS.MyGame.UI.Panel;迁移见 12-MIGRATION-ADAPTORS.md
闭合泛型 / 数组 export继续 zts.make_* / get_type_from_name
CommonJS requirev1 范围外
运行时依赖 .d.tsQuickJS 加载声明文件。生成契约、入库与 tsc14-TYPESCRIPT.md

3. 类型对象与 exotic 布局

三表布局与属性分派算法:metatable/01-LAYOUT.mdmetatable/02-INDEX.md

3.1 类型对象(静态门面)

每个 C# 类型对应类型对象 T + 静态分派载体 STO(Static Type Object dispatch):

T (类型对象,exotic)
├─ __assembly / __fullname / __name / __typeid / __by*InstanceProto / __klass
├─ StaticField / StaticMethod(经 STO 三表分派)
└─ ...

STO(内部槽 + 三表)
├─ 静态属性 get/set → method / fieldGetter / fieldSetter 三表
└─ [[Construct]] → 实例构造 dispatch(enum 无)

通过类型对象仅访问静态成员唯一例外new T(...) 触发 [[Construct]] 构造实例。

3.2 实例分派 IEO

与 STO 完全独立

IEO(ByVal 或 ByObj 实例 exotic)
├─ 实例属性 get/set → 实例三表(Bind 期已含继承成员)
├─ [[Finalize]] → ByObj:ObjectRegistry;ByVal:struct 释放
├─ length → 数组(§7.3)
└─ __type → 指回类型对象 T
instance exotic object
[[DispatchProto]] = IEO -- 门面 = 声明类型 / view
[[Payload]] = 对象指针或 struct 拷贝

同一托管对象可有多个 exotic object(不同 view);zts.cast 切换门面(spec/marshal/06-CLASS.md)。

禁止经实例属性分派 隐式访问静态成员;须使用类型对象 T 访问静态成员(见 §3.3)。

3.3 静实例互查

引用用途
T.__byvalInstanceProto → ByVal IEO构造时挂接
T.__byobjInstanceProto → ByObj IEO构造 class、boxed struct 等时挂接
instance.__typeTtypeof、register_method 域推断
TypeBinding持有 staticMap、byval/byobj instance map

3.4 延迟初始化(EnsureBinding)

类型 首次访问 时完整构建(仅 public):

  • 字段、无参/有参 property、方法、构造函数
  • 继承链 public 成员扁平写入 当前类型三表(§5)
  • [TsAlias] 换名后的最终名(可与其它方法默认名/别名重复,见 overload §5)

3.5 枚举

CSharp[...] 得类型对象 E

  • Bind 期:public static literal → 类型对象自有属性,值为 number(underlying 整型)
  • [[Construct]] / _default / _ctor
  • 默认跨边界:numberspec/marshal/08-ENUM.md);禁止 bigint
  • boxed 实例: zts.box(E, value) → ByObj
const Color = CSharp.AC['MyGame.Color'];
console.assert(Color.Red === 0);
const redBox = zts.box(Color, Color.Red);

3.6 Nullable<T>

闭合 Nullable<T> 类型对象 N

  • __nullable : true __byvalInstanceProto / __byobjInstanceProto / IEO
  • STO [[Construct]] → 构造 element 类型 T 的有值实参(非 Nullable 包装实例)
  • null → JS null不是 undefined;见 00-OVERVIEW.md §1.4)
const NullableInt = zts.make_generic_type(
CSharp.mscorlib['System.Nullable`1'],
zts.types.int32
);
CS.Service.Take(NullableInt(42)); // 有值:number
CS.Service.Take(null); // null

3.7 struct

类型对象含 __struct : true

[[Construct]] → 有参构造 dispatch → ByVal exotic object
_default() → 无参 default(T) exotic object(仅 struct,经 STO 静态分派回退)
const Point = CSharp.AC['MyGame.Point2D'];
const zero = Point._default();
const p = new Point(3, 4);
// 或 Point(3, 4) 若实现支持 callable 构造;规范推荐 new
  • 实例:ByVal exotic objectspec/marshal/05-STRUCT.md
  • 无继承;静态成员不向上查找(值类型无派生静态场景)

4. 成员暴露规则

4.1 可见性

public 进入绑定表。internal / protected / private 对 JS 不可见。

4.2 字段

访问实例静态
obj.fieldType.field
obj.field = vType.field = v

只读字段赋值 → 属性 set miss → throw。

4.3 属性

类型JS 访问
无参 propertyobj.prop / Type.prop(getter/setter 经三表)
有参 property(含索引器)get_PropName(...) / set_PropName(...) 方法形式

数组元素:get / set 实例方法(§7.4),不走 get_Item 命名,不用 arr[i] 原生下标(数组 exotic object 不实现 [[Get]] 整数键)。

4.4 方法

04-METHOD-OVERLOAD.md:单重 → direct function;多重 → dispatch;[TsAlias] / register_method

调用约定:

obj.instanceMethod(a, b); // ✅ 方法调用:自动传入 CLR this
const f = obj.instanceMethod;
f(a, b); // ❌ 提取函数:不自动绑定 this

Type.staticMethod(a, b); // 静态:无 this

4.5 事件(无专用对象)

不提供 Event 子对象 { get, set, fire }

C# event 在 JS 侧暴露为普通 add / remove 方法(与编译器生成名一致):

demo.add_ValueChanged((v) => console.log(v));
demo.remove_ValueChanged(handler);

若类型提供 raise/invoke 等 public 方法,按普通方法绑定; fire 特殊键。

4.6 构造函数

类型构造入口
class / structnew Type(...)[[Construct]];struct 另有 Type._default()
enumzts.box
Nullable<T>N(...)new N(...) → element T 的值;null 用 null
抽象类 / 接口无 public 构造则 construct throw
  • 构造 不参与继承;仅用 当前类型 声明的 public 实例构造函数
  • 禁止在类型对象挂与 [[Construct]] 等价的 _ctor 字段(struct 的 _default 除外)

5. 继承(Bind 期扁平化)

5.1 静态成员

静态属性分派在 staticMap 未命中时 递归查父类。

为与 C#「可通过派生类型名访问继承 static 成员」一致,在 EnsureBinding 将基类 public 静态成员 扁平复制 到派生 staticMap(派生同名覆盖)。

5.2 实例成员(Bind 期扁平化,无运行时 promotion)

不采用: 属性 miss 时沿继承链查找并 提升 到成员表(promotion)。绑定完成后 miss 即 throw

现行规范: 与静态相同,在 Bind 期 将基类 public 实例成员(字段、无参 property、方法)扁平写入 派生类型的 byvalInstanceMap / byobjInstanceMap 三表;派生声明 覆盖 基类同名项。

运行时属性 get/set:

1. 查 methodTable / fieldGetterTable / fieldSetterTable(及 STO 回退)
2. 命中 → 返回或调用
3. 未命中 → throw Error('zts: …')(见 metatable/02-INDEX.md)

步骤「沿继承链查找」或「提升到 instanceMap」。

虚方法: 仍通过 bridge 对 真实实例 虚派发;Bind 表项指向的子类 override bridge 保证 C# 语义。

5.3 方法与 dispatch 的继承

若继承树上同一 is_static 域存在多个 public 最终同名候选(含基类扁平化结果、[TsAlias] 撞名),Bind 后该键绑定 dispatch function。分派时候选列表含该最终名下全部 applicable 重载;选优规则见 04-METHOD-OVERLOAD.md §3.6、§5。


6. 泛型方法

针对 方法自身 带泛型参数,如 void Foo<T>(T a)。闭合泛型类上的方法 走本节。

6.1 调用约定

// Type.Foo 为 direct generic method function
const foo_int = zts.make_generic_method(Type.Foo, zts.types.int32);
foo_int(obj, value); // 静态则无需 obj

使用 05-LIB.md make_generic_method 单态化泛型方法 function。

6.2 缓存

相同 (genericMethodBase, typeArgs…) intern 为同一 inflated direct function(Il2Cpp:写入 NameMetaMap 内部签名键)。


7. 数组

7.1 创建

const arr = zts.new_szarray_by_element_type(zts.types.int32, 10);
const arr2 = zts.new_szarray_by_szarray_type(int_arr_type, 10);
const matrix = zts.new_mdarray_by_spec(zts.types.int32, [0,0], [2,3]);

7.2 length

形态arr.length
szarrayLength
mdarray∏ GetLength(d)(可寻址元素总数)

各维长度仍用 GetLength(dimension)

7.3 元素访问:get / set

实现 arr[i] 整数键访问(exotic object 不对 CLR 下标做 [[Get]]/[[Set]])。

arr.set(0, 10);
const v = arr.get(0);

matrix.set(0, 1, 7);
const x = matrix.get(0, 1);
API说明
get实参个数 = rank;返回元素类型的 JS 形态(基元未装箱)
setrank 个为 C# 下标(含 lowerBound),最后一参为 value

zts.to_array0 基 JS Array 不同(05-LIB.md §8.4)。

7.4 互转

API说明
zts.to_bytesblittable 元素 szarray → 按内存字节拷贝为 Uint8Array / binary string(实现二选一,须文档化)
zts.to_arrayszarray → JS Array(0..n-1 连续索引)

8. 特殊类型概要

类型说明
接口可解析;不可构造(无 public 构造)
抽象类仅 public 构造可 new
静态类仅静态成员;无 [[Construct]]
枚举§3.5;spec/marshal/08-ENUM.md
Nullable<T>§3.6
委托类型对象 + 实例 IEO [[Call]]spec/marshal/09-FUNCTION.md
struct§3.7;spec/marshal/05-STRUCT.md
classByObj;spec/marshal/06-CLASS.md

9. Mono / Il2Cpp 一致性

要求
CSharp 路径与 typeFullName一致
csharp: specifier / 导出名 / identity一致
静实例隔离一致
Bind 期继承扁平化一致
属性 miss → throw一致
Event → add_/remove_一致
构造、dispatch、泛型方法一致
数组 lengthget/set一致
方法 this 绑定规则一致
错误消息一致或等价(zts: 前缀)

10. 示例

import { Demo } from "csharp:Assembly-CSharp";
import { Panel } from "csharp:Assembly-CSharp/MyGame.UI";
import { Point2D } from "csharp:Assembly-CSharp/MyGame";
import { List } from "csharp:mscorlib/System.Collections.Generic";

const demo = new Demo();
const panel = new Panel();

const p = new Point2D(3, 4);
const zero = Point2D._default();

const ListInt = zts.make_generic_type(List, zts.types.int32);
const list = new ListInt();

demo.add_Changed(() => {});

const arr = zts.new_szarray_by_element_type(zts.types.int32, 4);
arr.set(0, 42);

等价的低层写法(调试、嵌套类型、adaptor 内部仍可用):

CSharp.AC = CSharp['Assembly-CSharp'];

const demo = new CSharp.AC.Demo();
const panel = new CSharp.AC['MyGame.UI.Panel']();
const Inner = CSharp.AC['MyGame.UI.Outer+Inner'];

11. 实现落点

主题Il2CppMono
类型懒加载TypeRegistryTsMonoAppDomain / MetaBinding
csharp: 虚拟模块JsLoader 拦截 + JS_NewCModule(或等价)同等:JS_SetModuleLoaderFunc 链,先于 宿主 moduleLoader
三表 indexerMetaBinding / Dispatch*exotic internal slots + JS 回调
继承扁平MetaBinding::EnsureBindingMetaBinding.cs
数组 get/setArrayMarshal + instance map等价绑定

细节见 impl/IL2CPP.mdimpl/MONO.md