Standard Library
interface IDisposable
The interface of an object that must be cleaned up when its work is finished.
since 0.1.0-alpha.1linuxwindowswasm
Overview
A class that implements IDisposable can be declared with using. The close method then runs exactly once when the enclosing block is left, however it is left: by reaching the end, by return, by break or continue, or by a thrown error. When a block has several using declarations, they are closed in the reverse of the order they were declared. File implements it.
Description
interface IDisposable { void close(); }
IDisposable is the contract that a using declaration requires. A type that implements it
promises that close() releases whatever the object holds, and a using declaration calls
close() for you on every way out of the block that declared it: reaching the end, return,
an uncaught throw, break and continue. The library types that implement it are File,
TaskGroup and InStream<T>. Your own classes opt in the same way, by naming IDisposable in
their declaration and defining close().
Rules
close()runs exactly once perusingdeclaration, on every exit from the block.- Several
usingdeclarations in one block close in reverse order: the last one declared is closed first. usingneeds a reference type (a class, not astruct) that implementsIDisposable. A type that only happens to have aclose()method does not qualify.TcpStreamis an example: call itsclose()yourself.- The
usingbinding cannot be reassigned. close()is looked up on the object's real class, so ausingwhose declared type isIDisposablestill runs the concrete class'sclose().- If
close()throws while another exception is already unwinding, the new exception replaces it. - Make
close()safe to call twice where you can. The library's stream and socket types are idempotent;File.close()is not, and throws if the file is already closed.
Examples
A class that implements IDisposable, used three ways. The block ends normally, throws, and
returns early; close() runs each time, and two resources in one block close in reverse order:
using closes resources on every exit
class Resource : IDisposable {
string name;
new Resource(string n) { name = n; console.writeln("open ${n}"); }
void close() { console.writeln("close ${name}"); }
}
void useBoth() {
using Resource first = Resource("first");
using Resource second = Resource("second");
console.writeln("working");
}
useBoth();
void failing() {
using Resource guarded = Resource("guarded");
throw RuntimeException("boom");
}
try {
failing();
} catch (RuntimeException e) {
console.writeln("caught ${e.message}");
}
int firstEven(Array<int> items) {
using Resource scan = Resource("scan");
for (int n in items) {
if (n % 2 == 0) { return n; }
}
return -1;
}
console.writeln(firstEven([1, 3, 4, 5]));
open first
open second
working
close second
close first
open guarded
close guarded
caught boom
open scan
close scan
4
Notes
Namespace-level constants of the standard library, such as std::read, are initialized before the
program runs. std::read, std::write, std::append and std::binary are const: they are
facts, not variables, and assigning to one is a compile error (cannot assign to const 'read').
Examples
class Resource : IDisposable {
string name;
new Resource(string n) {
name = n;
console.writeln("open ${n}");
}
void close() {
console.writeln("close ${name}");
}
}
void work() {
using Resource a = Resource("a");
using Resource b = Resource("b");
console.writeln("working");
}
work();
open a
open b
working
close b
close a
Methods
close
close() -> voidReleases what the object holds.
A using declaration calls it for you. Implement it so that it is safe to run once; do not call it yourself on an object that a using declaration owns, or it will run twice.
Examples
class Lock : IDisposable {
bool held = true;
void close() {
held = false;
}
}
Lock lock = Lock();
console.writeln(lock.held);
lock.close();
console.writeln(lock.held);
true
false
See also
- File — An open file.
- TaskGroup — A set of tasks that live and end together.
- InStream — The reading end of a stream: a queue of values of type
Tthat something else produces. - using — deterministic cleanup — A using declaration owns a resource and closes it exactly once on every way out of its block, in reverse order of declaration.