C#: typed access and object lifetime
GetEntity, GetEntityOrNull, nullable and a freed Entity in a complete component.
Choose missing-object behavior
| Operation | Purpose |
|---|---|
| GetEntity<T>(path) | Required object; a wrong existing type throws InvalidCastException |
| GetEntityOrNull<T>(path) | Optional object; a missing path or incompatible type returns null |
| value is T typed | C# type check on an existing value |
| ReckfellObject.IsInstanceValid(value) | Check that its native object still exists |
Do not silently make every required dependency nullable: a broken level structure should remain visible. Missing optional Status is expected below and reported through bool.
ScriptBoundary.cs
using Reckfell;
public partial class ScriptBoundary : Entity
{
public int Count { get; private set; }
public bool Add(int amount)
{
if (amount <= 0 || Count > int.MaxValue - amount) return false;
Count += amount;
return true;
}
public bool ShowOnChild(string text)
{
Label? label = GetEntityOrNull<Label>("Status");
if (!ReckfellObject.IsInstanceValid(label)) return false;
label!.Text = text;
return true;
}
}Create an Entity with ScriptBoundary and a child Label named Status. ShowOnChild("Ready") changes its text. Without Status, or with an ordinary Entity at that path, it returns false. The fixture also verifies that a wrong required cast throws InvalidCastException.
Nullable does not validate native lifetime
After label.Free(), its managed reference can remain non-null. label != null and ?. do not establish that the native Label exists. Check IsInstanceValid before using retained references. QueueFree defers deletion; the object is not necessarily freed immediately afterward.
Do not retain lookup results without lifetime rules. Disconnect external handlers in _ExitTree; reentry and _Ready have specific behavior. Paths are relative to the current Entity; type checks fix neither a wrong path nor a different tree scope.
Where async belongs
Signals covers ToSignal and handlers. async alone neither moves code to a worker thread nor guarantees that an Entity survives an await. Do not move active-tree operations into Task.Run merely because pure .NET calculations can run there.