puerts
puerts copied to clipboard
[Unity] 继承C#类的JS类,其对象的引用问题
举个例子说明一下
// C#代码
class TreeNode
{
public object userData;
}
// TS代码
class MyNodeData extends System.Object
{
text: string;
}
const node = new TreeNode();
const userData = new MyNodeData();
userData.text = "test";
node.userData = userData; // 这里看起来像对userData产生了引用,实际上并没有,userData会被GC
rootNode.Add(node);
非常容易踩坑,是否应该在构造JS对象的时候维护一个 C#对象对JS对象的引用关系?
补充:
造了个神奇的玩意儿,然而发现Unity里ConditionalWeakTable支持的不好
static ConditionalWeakTable<object, Action> refTable = new ConditionalWeakTable<object, Action>();
public static void RefJSObject(this object o, Action callback)
{
refTable.Add(o, callback);
}
class MyNodeData extends System.Object {
constructor() {
super();
this.RefJSObject(() => this);
}
}
搞得太复杂了, 你用临时变量才会被释放, 把你的userData也放到对象属性里面不就完事了. 你用 ConditionalWeakTable 本质上也只是给你的类添加了一个字段用来保存, 而不是直接用const xxx来产生一个临时变量, 这个只是临时变量和对象生命周期的问题吧, 跟c#和ts的交互好像没有什么关系
@Joycraft 例子仅仅是为了说明这个问题,实际情况可能继承后添加很多JS这边特有的数据类型的成员. 一方面C#这边不好表达这些类型,另一方面不能总是修改C#代码. 想讨论一下这种继承能否很好的支持起来, 如果不能支持怎么告知使用者不要这样用.
需求: 用JS扩展C#类, JS部分要随C#对象一起销毁
ConditionalWeakTable的想法是给任意C#对象引用一个JS对象(通过JS函数捕获JS对象,然后通过Action让C#这边持有它的引用) 遇到的问题是:
-
ConditionalWeakTable mono下的实现似乎有问题 https://github.com/mono/mono/issues/13560, il2cpp下未验证
ConditionalWeakTable不支持, 可以自己用WeakReference配合Tick检测实现类似效果
-
产生了循环引用: ObjectPool引用C#对象, 必须等JS对象销毁; 而JS对象被Action引用, Action在WeakTable里被C#对象引用;
一个可能的解法: 添加到WeakTable的时候, 把ObjectPool里的变成若引用. 这样C#对象就能被释放, 从而打破循环引用.
@chexiongsheng
我的个人看法, 按照标准的JS行为, 这些临时变量就应该直接释放的, 如果你不想被释放, 就需显式的用对象的字段来储存. 如果实现了你说的这个特性, 本来按照标准js行为应该释放的反而没有被释放了,变成了隐式的自动储存, 而开发者反而需要去维护循环引用的问题, 一旦开始循环引用, 那么正确的释放反而成了难题, 本来之前js开发者根据标准行为养成的编程习惯, 估计会对这种非标准行为很困惑.
如果这类的需求很多, 其实可以作为一个特定的框架来实现, 而不应该由通用的内核和底层来自带, 作为框架的标准行为是没有问题的.
@littlesome
@Joycraft 可能例子没说清楚,rootNode是树控件的一个成员,不是临时的,而rootNode引用了node,node引用了userData; 从JS的使用角度只要rootNode不清空,userData就不应该被回收
node.userData = userData;
关键是这一句,目前的实现是“只会提取userData的C#部分进行赋值,JS部分不产生引用”,这个不符合JS用户的使用习惯,容易造踩坑
MyNodeData虽然是继承自System.Object, 但它实际创建的应该是js对象而非C#对象. 据我目前所知, js对象是不允许被C#引用的(引发GC问题), 所以你这儿创建的userData没有引用计数