{"record":{"id":"81ae78ceeb24049e","repo":"egametang/ET","slug":"entity-is-disposed-instanceid-0","errorCode":null,"errorMessage":"entity is disposed, instanceid == 0!","messagePattern":"entity is disposed, instanceid == 0!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.core/Scripts/Core/Share/Entity/EntityRef.cs","lineNumber":65,"sourceCode":"            return left.Equals(right);\n        }\n\n        public static bool operator !=(EntityRef<T> left, EntityRef<T> right)\n        {\n            return !left.Equals(right);\n        }\n\n        private EntityRef(T t)\n        {\n            if (t == null)\n            {\n                this.instanceId = 0;\n                this.entity = null;\n                return;\n            }\n            if (t.InstanceId == 0)\n            {\n                throw new Exception(\"entity is disposed, instanceid == 0!\");\n            }\n\n            this.instanceId = t.InstanceId;\n            this.entity = t;\n        }\n        \n        public T Entity\n        {\n            get\n            {\n                if (this.entity == null)\n                {\n                    return null;\n                }\n                if (this.entity.InstanceId != this.instanceId)\n                {\n                    // 这里instanceId变化了，设置为null，解除引用，好让runtime去gc\n                    this.entity = null;","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.core/Scripts/Core/Share/Entity/EntityRef.cs#L47-L83","documentation":"Thrown by the EntityRef<T> constructor when wrapping an entity whose InstanceId is 0. InstanceId==0 means the entity has been disposed (or never registered). Holding a strong EntityRef to a disposed entity is unsafe, so the constructor rejects it.","triggerScenarios":"Constructing EntityRef on an entity after Dispose; capturing a disposed entity into EntityRef; an entity reference obtained from a stale cache whose InstanceId reset to 0 after recycling.","commonSituations":"Storing EntityRef across an await and the target was disposed meanwhile; pooled entities reused after Dispose (InstanceId reset); event handlers firing with a disposed sender.","solutions":["Check `entity != null && entity.InstanceId != 0` before constructing EntityRef.","Do not hold EntityRef across frames without re-validating; prefer weak references for caches.","Ensure Dispose is not called before all outstanding references are dropped."],"exampleFix":"// before\nvar r = new EntityRef<T>(entity);   // entity may be disposed\n\n// after\nif (entity == null || entity.InstanceId == 0)\n{\n    Log.Error(\"target entity disposed, skip EntityRef\");\n    return;\n}\nvar r = new EntityRef<T>(entity);","handlingStrategy":"type-guard","validationCode":"if (entity != null && entity.InstanceId != 0)\n{\n    var r = new EntityRef<T>(entity);\n}","typeGuard":"static bool IsLive<T>(T e) where T : Entity\n    => e != null && e.InstanceId != 0;","tryCatchPattern":null,"preventionTips":["Check InstanceId != 0 before wrapping in EntityRef.","Do not hold EntityRef across awaits without re-validating.","Avoid constructing refs in dispose/cleanup paths."],"tags":["entity","entityref","disposed","core"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}