Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a void version of Lazy<T>?

I want to use the behavior of Lazy<T> in my class to make sure that a certain operation happens once and only once. I have done this before by having a Lazy that essentially calls a Func that does something and then returns a null value. I don't care about the return value, I just want to make sure the thing only happens once.

I'm thinking it could be called Once. I'll build it myself and use a Lazy internally if it doesn't already exist, but I thought ask before doing that. Thanks!

like image 593
skb Avatar asked Mar 17 '14 14:03

skb


3 Answers

It does not exist yet. Use a Lazy<object> and return null from the factory.

You can encapsulate that into a Once class like you said but don't inherit from Lazy<object> because that would be a misuse of inheritance. Use proper encapsulation.

You can also use the LazyInitializer class which is a matter of taste.

like image 124
usr Avatar answered Oct 09 '22 16:10

usr


If you don't need absolute control over when the initialization occurs, you could use a static constructor of one of your classes. Otherwise you could use the following:

You can either use Lazy<T> or LazyInitializer. Here is an example of the latter.

private object _initializationObject;

// this is used to ensure the initialization function only runs once, even in
// multi-threaded scenarios
private bool _initialized;
private readonly object _initializationLock = new object();

private void Initialize()
{
  // run the initialization once
  LazyInitializer.EnsureInitialized(
    ref _initializationObject, ref _initialized,
    _initializationLock, InitializeImpl);
}

private object InitializeImpl()
{
  // initialization code...

  return null;
}
like image 37
Sam Harwell Avatar answered Oct 09 '22 16:10

Sam Harwell


As mentioned, are great ideas to achieve what you want

1) Use Lazy<object> returns null..
2) Use LazyInitializer.EnsureInitialized<T> returns null too..
3) Use a Singleton Pattern or something like it...

But I recommend another approach

Use Task initialization, you can check more details here: http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html

The basics ideia is to create a task, you do not necessary need perform asynchronous, you only need to wait for its completed, and if it is completed, the method proceeds directly.

All ways are very similar, feel free to choose the one which fits in your solution.

like image 43
J. Lennon Avatar answered Oct 09 '22 17:10

J. Lennon