Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Unity] 继承C#类的JS类,其对象的引用问题 #65

Open
littlesome opened this issue Oct 17, 2020 · 7 comments
Open

[Unity] 继承C#类的JS类,其对象的引用问题 #65

littlesome opened this issue Oct 17, 2020 · 7 comments
Assignees

Comments

@littlesome
Copy link
Contributor

举个例子说明一下

// 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对象的引用关系?

@littlesome
Copy link
Contributor Author

补充:

造了个神奇的玩意儿,然而发现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);
    }
}

@PleijaEternal
Copy link

PleijaEternal commented Oct 17, 2020

搞得太复杂了, 你用临时变量才会被释放, 把你的userData也放到对象属性里面不就完事了.
你用 ConditionalWeakTable 本质上也只是给你的类添加了一个字段用来保存, 而不是直接用const xxx来产生一个临时变量, 这个只是临时变量和对象生命周期的问题吧, 跟c#和ts的交互好像没有什么关系

@littlesome
Copy link
Contributor Author

@Joycraft
例子仅仅是为了说明这个问题,实际情况可能继承后添加很多JS这边特有的数据类型的成员. 一方面C#这边不好表达这些类型,另一方面不能总是修改C#代码.
想讨论一下这种继承能否很好的支持起来, 如果不能支持怎么告知使用者不要这样用.

@littlesome
Copy link
Contributor Author

littlesome commented Oct 18, 2020

需求: 用JS扩展C#类, JS部分要随C#对象一起销毁

ConditionalWeakTable的想法是给任意C#对象引用一个JS对象(通过JS函数捕获JS对象,然后通过Action让C#这边持有它的引用)
遇到的问题是:

  1. ConditionalWeakTable mono下的实现似乎有问题 ConditionalWeakTable not implemented for Boehm GC mono/mono#13560, il2cpp下未验证

    ConditionalWeakTable不支持, 可以自己用WeakReference配合Tick检测实现类似效果

  2. 产生了循环引用: ObjectPool引用C#对象, 必须等JS对象销毁; 而JS对象被Action引用, Action在WeakTable里被C#对象引用;

    一个可能的解法: 添加到WeakTable的时候, 把ObjectPool里的变成若引用. 这样C#对象就能被释放, 从而打破循环引用.

@chexiongsheng

@PleijaEternal
Copy link

PleijaEternal commented Oct 19, 2020

我的个人看法, 按照标准的JS行为, 这些临时变量就应该直接释放的, 如果你不想被释放, 就需显式的用对象的字段来储存. 如果实现了你说的这个特性, 本来按照标准js行为应该释放的反而没有被释放了,变成了隐式的自动储存, 而开发者反而需要去维护循环引用的问题, 一旦开始循环引用, 那么正确的释放反而成了难题, 本来之前js开发者根据标准行为养成的编程习惯, 估计会对这种非标准行为很困惑.

如果这类的需求很多, 其实可以作为一个特定的框架来实现, 而不应该由通用的内核和底层来自带, 作为框架的标准行为是没有问题的.

@littlesome

@littlesome
Copy link
Contributor Author

littlesome commented Oct 19, 2020

@Joycraft 可能例子没说清楚,rootNode是树控件的一个成员,不是临时的,而rootNode引用了node,node引用了userData;
从JS的使用角度只要rootNode不清空,userData就不应该被回收


node.userData = userData;

关键是这一句,目前的实现是“只会提取userData的C#部分进行赋值,JS部分不产生引用”,这个不符合JS用户的使用习惯,容易造踩坑

@throw-out
Copy link
Contributor

MyNodeData虽然是继承自System.Object, 但它实际创建的应该是js对象而非C#对象.
据我目前所知, js对象是不允许被C#引用的(引发GC问题), 所以你这儿创建的userData没有引用计数

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants