Introduction
The “Lazy Loading” design pattern actually equips the developer with the art of providing data only when a property is called for. In other words, it is a on-demand loading. It is an efficient technique to improve performance.
Using the code
For the explanation, I have taken a simple scenario. Say we have classes PersonalLoan
and Loan
, as shown below.
public class PersonalLoan
{
public string AccountNumber { get; set; }
public string AccounHolderName { get; set; }
public Loan LoanDetail { get; set; }
public PersonalLoan(string accountNumber)
{
this.AccountNumber = accountNumber;
this.AccounHolderName = getAccounHolderName(accountNumber);
}
}
public class Loan
{
public string AccountNumber { get; set; }
public float LoanAmount { get; set; }
public bool IsLoanApproved { get; set; }
public Loan(string accountNumber)
{
Console.WriteLine("loan class constructor called.....");
this.AccountNumber = accountNumber;
this.LoanAmount = 1000;
this.IsLoanApproved = true;
Console.WriteLine("loan object created.....");
}
}
For explanation's sake, we will assume that AccountNumber
and AccounHolderName
are not so costly operations in terms of memory occupation and time consumption. On the other hand, LoanDetail
is a costly operation and is not used so often. So while designing a class, we may expect that it is better not to have the detail and to populate it when the object property “LoadDetail
” is accessed. Please note that the PersonalLoan
constructor does not load the LoanDetail
property right this point.
In order to archive LazyLoading, we need to change our code a little and it should look like:
public class PersonalLoan
{
private Loan _loanDetail;
public string AccountNumber { get; set; }
public string AccounHolderName { get; set; }
public Loan LoanDetail
{
get { return _loanDetail ?? (_loanDetail = new Loan(this.AccounNumber)); }
}
public PersonalLoan(string accountNumber)
{
this.AccounNumber = accountNumber;
this.AccounHolderName = getAccounHolderName(accountNumber);
}
}
In this way, we make sure that “LoanDetail
” will be populate only when the property is called rather than when the object for “PersonalLoan
” is instantiated. For details, please check PersonalLoan.cs in the attached project.
Now taking this a step ahead, let's look what .NET 4.0 has in this respect. 4.0 introduces a “Lazy<T>
” class to support lazy initialization, where “T
” specifies the type of object that is being lazily initialized. This is a new feature of C# 4.0 and it can be used when we are working with large objects. The implementation is quite similar to what we have done in the last example.
public class PersonalLoanLazyClass
{
private readonly Lazy<Loan> lazyLoan;
public string AccountNumber { get; set; }
public string AccounHolderName { get; set; }
public Loan LoanDetail
{
get { return this.lazyLoan.Value; }
}
public PersonalLoanLazyClass(string accountNumber)
{
Console.WriteLine("PersonalLoanLazyClass Object Initializ: call to costructor....");
this.AccountNumber = accountNumber;
this.AccounHolderName = getAccounHolderName(accountNumber);
this.lazyLoan = new Lazy<Loan>(() => new Loan(this.AccountNumber));
Console.WriteLine("Completed initialization.......");
}
}
For details, please check PersonalLoanLazyClass.cs in the attached project. You can check out lazy loading by adding the following lines of code to the executing program:
static void Main(string[] args)
{
var personalLoan = new PersonalLoanLazyClass("123456789");
Console.WriteLine("\n\n.......................Press Enter " +
"to continue.......................\n\n");
Console.Read();
Console.WriteLine(personalLoan.LoanDetail.LoanAmount.ToString());
Console.Read();
Console.Read();
}
Output:
