Implementation of Lazy<T> for .NET 3.5

.NET 4.0 has a nice utility class called System.Lazy that does lazy object initialization. I would like to use this class for a 3.5 project. One time I saw an implementation somewhere in a stackoverflow answer but I can't find it anymore. Does someone have an alternative implementation of Lazy? It doesn't need all the thread safety features of the framework 4.0 version.

Updated:

Answers contain a non thread safe and a thread safe version.

Answers


Here is an implementation that I use.

/// <summary>
/// Provides support for lazy initialization.
/// </summary>
/// <typeparam name="T">Specifies the type of object that is being lazily initialized.</typeparam>
public sealed class Lazy<T>
{
    private readonly object padlock = new object();
    private readonly Func<T> createValue;
    private bool isValueCreated;
    private T value;

    /// <summary>
    /// Gets the lazily initialized value of the current Lazy{T} instance.
    /// </summary>
    public T Value
    {
        get
        {
            if (!isValueCreated)
            {
                lock (padlock)
                {
                    if (!isValueCreated)
                    {
                        value = createValue();
                        isValueCreated = true;
                    }
                }
            }
            return value;
        }
    }

    /// <summary>
    /// Gets a value that indicates whether a value has been created for this Lazy{T} instance.
    /// </summary>
    public bool IsValueCreated
    {
        get
        {
            lock (padlock)
            {
                return isValueCreated;
            }
        }
    }


    /// <summary>
    /// Initializes a new instance of the Lazy{T} class.
    /// </summary>
    /// <param name="createValue">The delegate that produces the value when it is needed.</param>
    public Lazy(Func<T> createValue)
    {
        if (createValue == null) throw new ArgumentNullException("createValue");

        this.createValue = createValue;
    }


    /// <summary>
    /// Creates and returns a string representation of the Lazy{T}.Value.
    /// </summary>
    /// <returns>The string representation of the Lazy{T}.Value property.</returns>
    public override string ToString()
    {
        return Value.ToString();
    }
}

If you don't need thread-safety, it's pretty easy to put one together with a factory method. I use one very similar to the following:

public class Lazy<T>
{
    private readonly Func<T> initializer;
    private bool isValueCreated;
    private T value;

    public Lazy(Func<T> initializer)
    {
        if (initializer == null)
            throw new ArgumentNullException("initializer");
        this.initializer = initializer;
    }

    public bool IsValueCreated
    {
        get { return isValueCreated; }
    }

    public T Value
    {
        get
        {
            if (!isValueCreated)
            {
                value = initializer();
                isValueCreated = true;
            }
            return value;
        }
    }
}

A somewhat simplify version of aaron's

public class Lazy<T> where T : new()
{ 
  private T value; 

  public bool IsValueCreated { get; private set;}

  public T Value 
  { 
    get 
    { 
        if (!IsValueCreated) 
        { 
            value = new T();
            IsValueCreated = true; 
        } 
        return value; 
    } 
  } 
} 

Some funny (but not very usable) stuff can be added: implicit coversion from delegate:

public static implicit operator Lazy<T>(Func<T> initializer)
{
    return new Lazy<T>(initializer);
}  

And usage

private static Lazy<int> Value = new Func<int>(() => 24 * 22);

C# compiler have some problem with performing this conversion, for example assigning lambda expression does not work, but it is one more thing causes your colleguas to think a bit :)


Need Your Help

Undocumented UPS API question

php api rest integration ups

At work, I'm working on including UPS integration for our product's shopping cart. I'm currently using the documented API, which supplies WSDLs. To use this API, you need a username, password and A...

Dynamically setting NSString vars in a loop

iphone objective-c xcode sdk

I am building an iphone game. I have a set of NSStrings that I set periodically throughout the game life cycle. I am finding that I am in need of setting the same NSStrings often and looping throug...