# using / IDisposable

> C#'s `using`, exactly: `Dispose()` is called on every way out of the block — normal exit, return, break, continue, or an exception — last declared first. The resource must be an `IDisposable`, and the block may not hold a durable wait.

<!-- id: function-using · area: function · stability: stable · html: https://osysharp.com/reference/function/using/ -->

## Summary        {#summary}
`using` is C#'s, and it means what C# says it means: the resource's `Dispose()` runs on **every** way out of the
block — falling off the end, `return`, `break`, `continue`, or an exception on its way out — and a `using var`
declaration lasts to the end of its enclosing block, with several of them disposed **last declared first**.

The platform owns the lifetime of everything it hands you — rows, HTTP calls, files — so none of those need a
`using`. You reach for one when your class holds something **outside** Osy#: a session opened on an external
database, a multipart upload started on a bucket, a lease taken on a remote lock. That class implements
`IDisposable` with its own `Dispose()`:

```osy title="a remote session, closed on every way out" test app=function-using-session
app Warehouse {
  model "model/**/*.osy";
  use Osysharp.Http;       // the manifest dependency that makes `Http.*` available
}

class WarehouseSession : IDisposable {
  public string Id = "";
  public bool Closed;

  public static WarehouseSession Open() {
    var r = Http.Post("https://warehouse.example.com/sessions", "{}", "application/json");
    return new WarehouseSession { Id = r.Body };
  }

  public void Dispose() {
    if (Closed) { return; }
    Http.Delete($"https://warehouse.example.com/sessions/{Id}");
    Closed = true;
  }
}

int CountRows(string table) {
  using (var session = WarehouseSession.Open()) {
    var r = Http.Get($"https://warehouse.example.com/sessions/{session.Id}/count/{table}");
    if (!r.IsSuccess) { return 0; }     // the session is closed here too
    return int.Parse(r.Body);
  }                                      // …and here
}
```

## Signature      {#signature}
```osy syntax
using (var r = <expression>) <statement-or-block>          // the statement form
using (<Type> a = <expression>, b = <expression>) { … }      // several of one type — b is disposed before a
using (<expression>) { … }                                   // dispose a value you already hold
using var r = <expression>;                                  // the declaration form — to the end of the block
```

## Description    {#description}
### What it lowers to {#lowering}
Exactly C#'s lowering, onto the `try`/`finally` the language already runs on the server and in the browser:

```osy syntax
using (var r = Open()) { Work(r); }
// is
{ var r = Open(); try { Work(r); } finally { r?.Dispose(); } }
```

So the resource is created **before** the `try` — if creating it throws, there is nothing to dispose — and a null
resource is skipped rather than dereferenced. Everything `finally` promises, `using` promises: see
[try / catch / finally](https://osysharp.com/reference/function/try-catch/).

### The declaration form, and the order {#order}
`using var r = …;` is scoped to the end of the block it is in. Two of them dispose in **reverse** order, because the
second one is nested inside the first — the newest resource is released before the one it may depend on:

```osy title="last declared, first disposed" test app=function-using-order
class Step : IDisposable {
  public string Name = "";
  public Trail Into = new Trail();
  public void Dispose() { Into.Log = Into.Log + Name; }
}

class Trail {
  public string Log = "";
  public void Run() {
    using var first = new Step { Name = ",1", Into = this };
    using var second = new Step { Name = ",2", Into = this };
    Log = "body";
  }                              // second is disposed, then first
}

string Order() {
  var trail = new Trail();
  trail.Run();
  return trail.Log;              // "body,2,1"
}
```

A `using` declaration needs a block to end in, so the body of a brace-less `if` cannot be one — C# refuses it too
(CS1023). Write braces, or the statement form.

### `IDisposable` is a real contract {#idisposable}
`IDisposable` is an ordinary interface with one member, `void Dispose()`, and a class takes it the way it takes any
contract — `class Lease : IDisposable { public void Dispose() { … } }` ([Interfaces — a contract several types can satisfy](https://osysharp.com/reference/class/interfaces/)). `using` over a value
that is not an `IDisposable` is refused, as C# refuses it (**CS1674**): there would be nothing to call.

```osy syntax
class Note { public string Text = ""; }
using (var n = new Note()) { … }   // ✗ 'Note' is not IDisposable, so `using` has nothing to dispose (CS1674)
```

If there is genuinely nothing to release, there should be no `using` — keep the declaration and drop the word.

### The one Osy# rule: no durable wait inside {#durable-wait}
A body in Osy# can **park**: an awaited `Workflow.Run`, a saga step (`await saga.Run(…)`, `await
saga.DisposeUnwind()`), a join (`await Workflow.WhenAll/WhenAny/When(…)`), or a `Workflow.Once(…, retry: …)` can
suspend the run and resume it later on another process — after a restart, a deploy, days later. A resource held
across that gap is not one anybody can rely on, so a `using` scope may not contain one:

```osy syntax
using (var lease = Lease.Take()) {
  await Workflow.Run("ship", order);   // ✗ a disposable can't be held across a durable wait;
}                                       //   close it before waiting, or open it again after
```

Close it before the wait, or open it again after. Ordinary calls inside a `using` — HTTP, reads, writes, other
functions — are fine; only the waits that suspend the run are refused. As in .NET, a process that dies mid-block
skips `Dispose()`: write `Dispose()` so the far side expires what it leaked (a session timeout, a lease's TTL).

### Not the `using` at the top of a file {#directive}
`using Osysharp.Http;` at the top of a file is the namespace import it looks like — a different construct that
happens to share the word. And `await using var saga = Workflow.BeginSaga();` is the saga's compensation scope, not
resource disposal; see the workflow docs.

## See also       {#see-also}
- [try / catch / finally](https://osysharp.com/reference/function/try-catch/) — the `finally` a `using` lowers to, and what it guarantees
- [Interfaces — a contract several types can satisfy](https://osysharp.com/reference/class/interfaces/) — implementing a contract, `IDisposable` included
- [The C# Osy# leaves out — and why](https://osysharp.com/reference/function/csharp-exclusions/) — the C# that Osy# leaves out, and why
- [Classes](https://osysharp.com/reference/class/index/) — classes are reference types, which is why `Dispose()` can update the object you passed in
