Skip to content

Instantly share code, notes, and snippets.

@stand-sure
Created December 3, 2020 20:24
Show Gist options
  • Save stand-sure/c06092289592479c100754000294d482 to your computer and use it in GitHub Desktop.
Save stand-sure/c06092289592479c100754000294d482 to your computer and use it in GitHub Desktop.
Async version of Lazy<T>
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
//// inspired by Stephen Toub's https://devblogs.microsoft.com/pfxteam/asynclazyt/
/// <summary>
/// Provides support for async lazy initialization.
/// </summary>
/// <typeparam name="T">Specifies the type of element being lazily initialized.</typeparam>
/// <remarks>
/// Use cases:
/// <list type="bullet">
/// <item>The non-async factory is slow and awaiting it is desirable.</item>
/// <item></item>
/// </list>
/// </remarks>
public class AsyncLazy<T> : Lazy<Task<T>>
{
/// <summary>
/// Initializes a new instance of the <see cref="AsyncLazy{T}" /> class
/// that uses a specified initialization function.
/// </summary>
/// <param name="valueFactory">
/// The <see cref="Func{T}" /> invoked
/// to produce the lazily-initialized value when it is needed.
/// </param>
public AsyncLazy(Func<T> valueFactory)
: base(() => Task.Factory.StartNew(valueFactory))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AsyncLazy{T}" /> class
/// that uses a specified task initialization function.
/// </summary>
/// <param name="taskFactory">
/// The <see cref="Func{U}" /> invoked to produce a lazily-initialized <see cref="Task{T}" /> when it is needed.
/// </param>
public AsyncLazy(Func<Task<T>> taskFactory)
: base(() => Task.Factory.StartNew(taskFactory).Unwrap())
{
}
/// <summary>
/// Allows <code>await foo</code> in lieu of <code>await foo.Value</code>.
/// </summary>
/// <returns>A <see cref="TaskAwaiter{T}" />.</returns>
public TaskAwaiter<T> GetAwaiter() { return this.Value.GetAwaiter(); }
/*
* this.Value is Task<T>
*/
/// <summary>
/// Gets the value.
/// </summary>
/// <returns>
/// The <see cref="T" />.
/// </returns>
/// <remarks>
/// This method is intended for scenarios
/// where <code>await foo</code> is not viable
/// (e.g. in properties).
/// </remarks>
public T GetValue()
{
return this.GetAwaiter().GetResult();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment