Resources and using
Not everything that needs cleanup is memory — files, sockets, mutexes, OS handles and the like are resources, and
ARC doesn’t know when to release them. IDisposable and using give that a deterministic answer.
interface IDisposable{ void Dispose();}A resource struct implements IDisposable and internally holds a managed reference to the actual resource, so
copying the struct shares the resource rather than duplicating it:
var a = File.Open("test.txt");var b = a; // b references the same open file as a
a.Dispose(); // releases a's reference// b still works: the underlying resource stays open until every reference is disposedusing guarantees Dispose() runs when the scope is left — including via return, break, continue, or an
error propagated with try. Two forms are available:
Error<string> Load(string path){ using file = try File.Open(path); // Dispose() runs when Load returns, however it returns return try file.ReadAllText();}
using (var file = File.Open("test.txt")){ file.Write("Hello");} // Dispose() runs hereThe value of using (...) does not need a name: using (expr) { ... } disposes the value of expr at the end of the
block. That suits begin/end pairs, such as the rows and panels of a user interface:
using (ui.Row()){ if (ui.Button("-")) count -= 1; if (ui.Button("+")) count += 1;} // the row ends hereWith several nested using declarations, cleanup runs in reverse order — last acquired, first released.