Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to lazy initialize generic List<T> via class extension

Tags:

c#

.net

generics

I'm trying to write safeAdd extention function for List class, so if it's not initialized yet - initialize it and add new value. But after I return from extension method, my just initialized list equals null. What's wrong?

Test class:

private class Test 
{
    public Test()
    {
        Id = Guid.NewGuid();
        //items = new List<string>();
    }
    public Guid Id { get; set; }
    public List<string> items { get; set; }
}

Extensions class:

public static class Helpers
{
    public static void safeAdd<T>(this List<T> list, T item)
    {
        if (list == null)
            list = new List<T>();
        list.Add(item);
    }
}

Part of main:

Test t = new Test();
t.items.safeAdd("testWord");
//Here t.items == null; WHY?
like image 509
Jentor Avatar asked Dec 26 '11 19:12

Jentor


People also ask

What is Lazy T in C#?

The Lazy<T> object ensures that all threads use the same instance of the lazily initialized object and discards the instances that are not used.

What is lazy initialization in Java?

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.

Is C# Lazy thread safe?

By default, Lazy<T> objects are thread-safe. That is, if the constructor does not specify the kind of thread safety, the Lazy<T> objects it creates are thread-safe.

Is lazy initialization good?

Lazy initialization is useful when calculating the value of the field is time consuming and you don't want to do it until you actually need the value. So it's often useful in situations where the field isn't needed in many contexts or we want to get the object initialized quickly and prefer any delay to be later on.


1 Answers

You have only assigned to a local method variable (which exists only inside the extension method) - this doesn't do anything to invoke the set, and to be honest there's no convenient way to get access to both the get and set without being verbose, or using lots of reflection / Expression code. IMO just do it in the class:

private List<string> items;
public List<string> Items { get {
     return items ?? (items = new List<string>()); } }

This will automatically initialize and assign the list the first time it is accessed.

It wouldn't be thread-safe unless I sync'd, or (perhaps preferable) used Interocked.CompareExchange for the assign. View  Interlocked it could be made thread-safe easily enough, but this is rarely a requirement for instance methods, and has associated overhead

like image 166
Marc Gravell Avatar answered Oct 17 '22 06:10

Marc Gravell