# Resources and deterministic cleanup

> Use using and ensure to dispose streams, subscriptions, and other resources at predictable points.

Canonical: https://alice-lang.org/documentation/advanced/resources/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

## Memory lifetime is not resource lifetime

The GC handles managed object reachability. A file handle, socket, stream, timer, or native allocation can need cleanup at a predictable point. Use the API's `IDisposable` contract rather than waiting for memory collection. See [.NET disposal guidance](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose).

## Use a scoped resource

Alice supports a `using` resource block. It invokes `Dispose` when control leaves the block, including through an exception.

```alice
class Resource < IDisposable
  def Dispose
    puts "disposed"
  end
end
using resource = Resource.new
  puts "working"
end
```

Expected output:

```text
working
disposed
```

[Edit and run in the Alice playground](https://playground.alice-lang.org/#code=u.Y2xhc3MgUmVzb3VyY2UgPCBJRGlzcG9zYWJsZQogIGRlZiBEaXNwb3NlCiAgICBwdXRzICJkaXNwb3NlZCIKICBlbmQKZW5kCnVzaW5nIHJlc291cmNlID0gUmVzb3VyY2UubmV3CiAgcHV0cyAid29ya2luZyIKZW5k)

This is different from `using System.Text`, which imports a namespace. `using resource = expression ... end` establishes a disposal scope for the returned object.

```alice
using stream = System.IO.MemoryStream.new
  stream.WriteByte(42)
  puts stream.Length
end
```

Keep all work that needs the resource inside its lifetime. Returning a reference to a disposed object does not extend that lifetime.

## Ensure for explicit cleanup

Use `begin`/`ensure` when cleanup is not represented by `IDisposable`, or when a lease must be returned to a pool:

```alice
stream = System.IO.MemoryStream.new
begin
  stream.WriteByte(42)
ensure
  stream.Dispose()
end
```

Acquire the resource before entering the protected work, and ensure every successfully acquired resource has one clear cleanup owner. Do not dispose a shared object merely because a helper temporarily borrowed it; follow the called API's ownership contract.

## Subscriptions

An event publisher can retain its subscribers. Save the delegate used for registration so the same handler can be removed:

```alice
count = Atomic.new(0)
handler = ->(sender : Object?, event : EventArgs) { count.add(1) }
component = System.ComponentModel.Component.new
component.Disposed += handler
component.Disposed -= handler
component.Dispose()
puts count.get
```

This prints zero because the handler is removed before disposal. A newly created equivalent lambda is not the original subscription.

## Asynchronous lifetimes

An async operation can outlive the method that started it. Await or otherwise join work before disposing a resource it still uses. Cancellation requests stopping; it does not itself prove that the operation has completed or relinquished its buffer.

Some .NET APIs expose `IAsyncDisposable`. Use their async cleanup contract deliberately; this book does not claim that a synchronous Alice `using` block automatically invokes `DisposeAsync`. Where needed, call and await the appropriate API from an async method and test failure paths.

## Test cleanup paths

Use a small test resource that records `Dispose` calls. Test normal completion and an exception inside the scope. For channels and actors, also test closure/draining so no consumer is left waiting after a producer fails.

## Continue reading

- Previous: [Memory and value semantics](https://alice-lang.org/documentation/advanced/memory.md)
- Next: [Spans, buffers, and pooling](https://alice-lang.org/documentation/advanced/buffers.md)
