I recently started trying to use the Lazy class to implement lazy loading. However, I'm finding that doing so does not seem to have any advantages over simply implementing it myself via a null-coalescing operator.
For example, if I want to have Task lazy-load a Contact, I can do it like so:
public class Task
{
[NotNull] private readonly IContactRepository _contactRepo;
[NotNull] private readonly Lazy<Contact> _lazyContact;
public readonly int? ContactFk;
public Task([NotNull] IContactRepository contactRepo, int? contactFk)
{
ContactFk = contactFk;
_contactRepo = contactRepo;
_lazyContact = new Lazy<Contact>(LoadContact);
}
[CanBeNull]
public Contact Contact => _lazyContact.Value;
[CanBeNull]
private Contact LoadContact() => !ContactFk.HasValue
? null
: _contactRepo.GetContact(ContactFk.Value) ??
throw new DataException($"No Contact found for Id {ContactFk}");
}
However, previously, I was accomplishing it like so:
public class Task
{
[NotNull] private readonly IContactRepository _contactRepo;
[CanBeNull] private Contact _lazyContact;
public readonly int? ContactFk;
public Task([NotNull] IContactRepository contactRepo, int? contactFk)
{
ContactFk = contactFk;
_contactRepo = contactRepo;
}
[CanBeNull]
public Contact Contact => !ContactFk.HasValue
? null
: _lazyContact ?? (_lazyContact =
_contactRepo.GetContact(ContactFk.Value) ??
throw new DataException($"No Contact found for Id {ContactFk}"));
}
Which to me seems to be more straight-forward. Instead of three fields, a property, a method, and an instantiation, it's just three fields and a property.
Is there something I'm missing to make the use of Lazy smoother? Some sort of extension method I can add or something?
Or should I just ignore Lazy and keep doing things as I have been?
Or does it depend on the circumstance?
Lazy<T>
also guarantees that the element will not be initialised more than once, and is thread-safe.