I came across a problem recently while implementing a singleton solution in a project I'm involved in. a singleton object is responsible for connecting to a backend API and on the construction of this singleton, it authenticates with the back-end and sets itself up for future access in anticipation for connections to the API that is responsible for communicating with.
This backend singleton should only need to communicate with the backend API when its told to, if it's not, it should not try to communicate with it.
Makes sense, however, each time you pass this singleton around as a function args, by virtue of it being evaluated as part of any function's arguments, it gets evaluated and thus constructed - even if that function doesn't end up calling anything on the singleton. And if you don't pass it around, you usually have no control when its constructed as its a static construct - merely loading the program initializes static variables first whether you were going to use it or not.
Ideally, if a condition within a function determines that it should contact the backend API, then it will use the singleton, otherwise, it just doesn't touch it. Can't do that by default.
What you could do is not have the initialization of the singleton authenticate with the backend however you'd need to call login() everytime you wanted to use the singleton. That could work and arguably it would be simpler...though I wanted it to work as-is without touching all the code to now call login() before first use etc...
The problem I was facing was that the singleton would still make its authentication request even when the function it was passed to was not using it. In short, the reason was that the singleton was being constructed when it was 'touched' or referenced like when you pass it in as a function argument as mentioned above.
So how do you arrange for the singleton to be 'touched' or passed around without being constructed until its 'used'? It turns that this is exactly what Lazy<T> is designed to do. You use it to allow you to pass around something like my singleton as a Lazy<MySingleton> and this protects the singleton from being initialized and when you want to use it, it will arrange for the construction of the underlying wrapped lazy<T> item when you explicitly call a method on it to 'Touch' it and thus initialize the construction routine of the object.
You use it to allow you to pass around something like my singleton as a Lazy<MySingleton> and this protects the singleton from being initialized and when you want to use it
Why worry about the singleton being initialized even when it's not going to be used, well its simple: If I have functionality that says turn off connecting to the backend, then I don't any backend functionality been used unless I explicitly ask for it, otherwise I won't and I expect no traffic to go to the backend API - even if its just a login request.
In most cases doing something when it's not needed causes slowness and is a hit the confidence of the solution if it doesn't do what it says it will do ie. not connect to the backend.
I came across the Lazy class from the Singleton guidance from http://csharpindepth.com/Articles/General/Singleton.aspx but never needed it, until inadvertently the authentication/login credentials that the backend singleton was using expired and when I thought, 'that's ok, I'll just not use that functionality' - I discovered that I got 'Access denied' exceptions being thrown in the code even though I'd turned off this ... I did but just because i was not using the Singleton, I was still referencing it.
# Make a lazy singleton. Lazy<MySingleton> lazySingleton = new Lazy<MySingleton>(()=> MySingleton.GetInstance())
This lazySingleton can be passed around and it will be protected from direct references to the underlying MySingleton object. When you want to actually directly access that object, you can access it through lazySingleton.Value;
I don't like that intermediate. Value call but that does the work, I usually wrap this in a call like this:
Lazy<MySingleton> mylazySingleton = new Lazy<MySingleton>(()=>MySingleton.GetInstance()); MySingleton BackendApi=> lazySingleton.Value; // Which allows me to call it this way BackendApi.Login() and it invokes the .Value property implicitly without you seeing it
That's the functionality I wanted, that's the functionality I got - lazy loading of a singleton to keep promises that I won't use that singleton until I explicitly do.