Lazy<T> wraps a value so computation happens on demand and the result is cached. It adds laziness to an ordinary workflow without changing the underlying value type. section 11.1
Lazy<T> belongs to a family of generic types that add capabilities while preserving the underlying workflow:
- Func<T> computes on demand, whereas Lazy<T> also caches the computed result. section 11.1
- Nullable<T> adds absence, Task<T> adds asynchronous computation, and IEnumerable<T> produces values incrementally. section 11.1
- A Lazy<T> can be created around a value, or around a computation that will produce that value later. section 11.1
Mapping and binding lazy computations
Map applies an ordinary function without forcing the original value immediately: it constructs a Lazy<R> whose Value access calls func(x.Value). If the function itself returns Lazy<R>, Bind avoids the unnecessary Lazy<Lazy<R>> nesting by flattening the result. section 11.3
static class LazyExtensions
{
public static Lazy<R> Map<T, R>(this Lazy<T> x, Func<T, R> func) =>
new Lazy<R>(() => func(x.Value));
}
The compact Map implementation makes deferred evaluation explicit: the function runs inside the new Lazy<R> rather than while Map constructs it. section 11.3
