Thursday, October 24, 2024

C# lazy initialization using Lazy class


In C#, the Lazy<T> class provides a way to defer the initialization of an object until it is actually needed. This is known as lazy initialization. The object is not created when the Lazy<T> instance is declared, but rather when the value is accessed for the first time. This approach is useful in scenarios where the creation of an object is resource-intensive or may not be necessary immediately.

Key Features:

  • Lazy Initialization: The object is created only when accessed, preventing unnecessary resource allocation.
  • Thread Safety: Lazy<T> supports thread-safe initialization, ensuring the object is created only once, even if accessed by multiple threads simultaneously.
  • Performance: Reduces startup time and memory usage by delaying object creation until it's required.

Look at the following code:
public class Program
{
    public static void Main(string[] args)
    {
        // Declaration of Lazy<Person> without initializing the Person object
        Lazy<Person> person = new();
        
        // Person object is not created yet
        Console.WriteLine("Person is not created yet, press any key to create it.");
        Console.ReadKey();

        // Accessing the Value property of Lazy<Person> triggers the creation of the Person object
        _ = person.Value;
        
        // Person object is now created
        Console.WriteLine("Person is created now.");
    }
}

Code Explanation:

  • A Lazy<Person> object named person is declared but not initialized immediately.
  • The message "Person is not created yet, press any key to create it." is displayed before the object is initialized.
  • The Person object is only instantiated when the person.Value is accessed, which happens after a key press.
  • The Person constructor is invoked, printing "inside CTOR: Person created", indicating that the object has been created.
  • Finally, the message "Person is created now." confirms the creation of the Person object.

Benefits:

  • Efficiency: The object is created only when needed, saving resources if it turns out that the object is not required during the program's execution.
  • Optimized Performance: Particularly useful when the initialization of the object is expensive, as the program doesn't pay this cost unless the object is actually needed.
This approach can be helpful in large applications where objects are resource-heavy but may not always be used.

Properties and methods of Lazy class

We have seen that the Lazy<T> class in C# provides mechanisms to defer the initialization of an object until it is first accessed. It offers several properties and methods to control and query the state of the lazy initialization.

Properties of Lazy<T>:

1. Value of Type: T
Description: Gets the value of the object that is lazily initialized. Accessing this property triggers the initialization of the object if it hasn’t been initialized yet.
Example:
Lazy<Person> lazyPerson = new Lazy<Person>();
Person person = lazyPerson.Value; // Triggers initialization
2. IsValueCreated of Type: bool
Description: Returns true if the object has already been initialized; otherwise, false.
Example:
Lazy<Person> lazyPerson = new Lazy<Person>();
bool created = lazyPerson.IsValueCreated; // Returns false until Value is accessed
ValueFactory (in some overloads):
3. Type: Func<T>
Description: The factory function used to initialize the value. This property is available when a custom factory method is provided in the constructor.
Example:
Lazy<Person> lazyPerson = new Lazy<Person>(() => new Person());

Methods of Lazy<T>:

1. ToString() of Type: string
Description: Returns the result of calling ToString() on the lazily initialized object (if it has been created). If the object hasn’t been created yet, it returns the type name Lazy<T>.
Example:
Lazy<Person> lazyPerson = new Lazy<Person>();
string description = lazyPerson.ToString(); // Returns type name if not initialized

2. CreateLazy() (available in Lazy<T> for the Lazy<T> overload using a custom value factory):
Description: Creates and returns a lazy object initialized with the value produced by the value factory.

Example:
Lazy<Person> lazyPerson = new Lazy<Person>();

// Checking if the value is created
Console.WriteLine(lazyPerson.IsValueCreated); // false

// Accessing the Value, triggering initialization
Person person = lazyPerson.Value; // Triggers initialization

// Checking if the value is created after access
Console.WriteLine(lazyPerson.IsValueCreated); // true

Summary:

Properties:
  1. Value to access the initialized object.
  2. IsValueCreated to check if the object has been initialized.
Methods:
  1. ToString() provides a string representation of the lazy object or the type name.

No comments:

Post a Comment

Hot Topics