# Naming a value in render

> A `render` block can name a value the way any C# block does — `var lapsed = …;` to infer the type, or `bool lapsed = …;` to declare it. The name is in scope for the rest of the block, so a value read twice is written once. A declared type pins the binding and is checked exactly as it is in a method body.

<!-- id: ui-render-binding · area: ui · stability: stable · html: https://osysharp.com/reference/ui/render-binding/ -->

## Summary        {#summary}

Inside `render { … }` a value can be given a name:

```osy syntax
var lapsed = DateTime.UtcNow > deadline;   // inferred from the initializer
bool lapsed = DateTime.UtcNow > deadline;  // declared, and checked
```

Both are the same binding. The name is visible to the **following siblings** in the block — not to anything before
it, and not outside it — which is the scope a C# local has.

## Signature      {#signature}

```osy syntax
var  <name> = <expression>;    // the type is inferred from the initializer
<Type> <name> = <expression>;  // the type is declared, and the initializer is checked against it
```

## Description    {#description}

### Why name a value at all   {#purpose}

A render expression is read where it is written, so a value used twice is otherwise written twice. Naming it once
is shorter to read and impossible to get subtly different in the second copy.

### Inferred or declared   {#typing}

`var` takes the initializer's type. A declared type **pins** the binding, which is not always the same thing:

```osy syntax
var half = 1;        // int    — `half / 2` is 0
decimal half = 1;    // decimal — `half / 2` is 0.5
```

The declared type is checked with the same rule a method body uses: the initializer must be assignable to it. A
derived value goes into a base-typed binding, a literal takes the C# constant conversion, and there is no implicit
conversion between `decimal` and `double` in either direction. An initializer that does not fit is a compile error
naming both types.

A binding must be initialized where it is declared — there is no definite-assignment analysis, so `bool flag;`
on its own is refused.

### What a binding cannot do   {#limits}

A binding names a value; it does not introduce a data read. Its initializer is held to the same client-runnable
rule as every other render expression, so it cannot reach the server, write state, or run an effect. A value that
needs a query belongs in a `live var` component field.

## Examples       {#examples}

A status label and a flag, each computed once and read several times:

```osy test app=ui-render-binding
[Page("/requests")]
[Render(CSR)]
[AllowAnonymous]
component Requests() {
  int[] ages = [1, 2, 5];

  render {
    Stack {
      // Declared, because the type is the point of the value.
      string heading = "Requests";
      Text(heading);

      foreach (var age in ages) {
        // Read twice below — written once here.
        bool lapsed = age > 3;
        Text($"{age}d: {(lapsed ? "lapsed" : "open")}{(lapsed ? " (closed)" : "")}");
      }
    }
  }
}
```

## See also       {#see-also}

- [component](https://osysharp.com/reference/ui/component/) — component fields, including `live var` for values that read data
- [Calling helpers from render](https://osysharp.com/reference/ui/render-calls/) — calling a pure helper from a render expression
