Declarations
weak fields
Hold a non-owning reference to an object that reads as None once the object is gone.
since 0.1.0-alpha.1linuxwindowswasm
Description
A weak field refers to an object without keeping it alive. It is meant for back-references such as
a child pointing to its parent, where a normal reference would form a cycle that keeps both
objects alive.
class Component {
weak IComponent? parent = None;
weak readonly IComponent? fixedParent = None;
}
The field's type must be an optional class or interface type, T?. Assigning a T, a T? or
None to the field is allowed and does not keep the referent alive. Reading the field gives a T?:
None once the last strong reference to the object has gone, and otherwise a normal reference to the
object. Because every read checks whether the object is still alive, copy the read into a local
variable before testing it for None and using it.
A weak field after its owner is released
class Parent { string name = "p"; }
class Child {
weak Parent? parent = None;
}
Child c = Child();
void attach(Child child) {
Parent temp = Parent();
child.parent = temp;
Parent? live = child.parent;
if (live != None) {
console.writeln("inside: " + live.name);
}
}
attach(c);
console.writeln(c.parent == None);
inside: p
true
While attach runs, temp owns the parent, so reading child.parent finds it. When attach
returns, temp is released, and the weak field reads as None.
Rules
weakapplies to instance fields only, and the declared type must beT?whereTis a class or interface. A struct, string, array, map,Blockor function type is a compile error.- Storing into a
weakfield does not retain the referent. - A read of the field returns a fresh
T?:Noneif the referent is gone, otherwise an ordinary reference. Once you hold that reference in a local variable, it keeps the object alive like any other. - The field itself cannot be narrowed.
if (c.p != None) { c.p.n }is rejected; copy it first withParent? p = c.p;and testp. - Weakness belongs to the field, not to the value. A weak read passed to a function, returned, or captured by a closure is an ordinary strong reference.
weak readonlyis allowed;weak constis a compile error.
Examples
Storing the only reference to a temporary leaves the weak field empty at once:
A temporary that is not kept alive
class Parent { string name = "p"; }
class Child { weak Parent? parent = None; }
Child c = Child();
console.writeln(c.parent == None);
c.parent = Parent();
console.writeln(c.parent == None);
true
true
The field cannot be narrowed directly:
Read into a local first
class P { int n = 1; }
class C { weak P? p = None; }
C c = C();
P x = P();
c.p = x;
if (c.p != None) { console.writeln(c.p.n); } // error: narrow the union before member access
P? local = c.p;
if (local != None) { console.writeln(local.n); } // fine
Notes
A weak field becomes None when the last strong reference is released. When you need a predictable
moment for that, keep the owner in a named variable and let it go out of scope; do not depend on the
release of a temporary that is passed as an argument.
See also
- Fields — Declare the data a class or struct holds, with optional initializers, and how a field without an initializer gets its default value.
- readonly fields — Fix an instance field once, either in its initializer or in every constructor, and keep it read-only afterwards.
- Classes — Declare reference types with fields, methods, constructors and accessors, with generics and inheritance from one or more base classes.