I've come across this piece of code where it looks like the original developer has tried to use a static string to cache a value in a static class.
public static class GetStringFromSomeProcess
{
private static string theAnswer;
public static string GetString
{
get
{
if(theAnswer == null)
{
theAnswer = GoGetTheAnswerFromALongRunningProcess();
}
return theAnswer;
}
}
}
As far as I can see this won't work, as you can't instantiate the GetStringFromSomeProcess
class, GoGetTheAnswerFromALongRunningProcess
will be called every time GetString
is used. Am I missing something?
Static data will cache exactly the same as any other data.
We can also initialize the value of the static variable while declaring it. The syntax for initializing the value of the static variable in C programming language is given below. Note: The value of a static variable can be reinitialized wherever its scope exists.
A variable declared static within a module (but outside the body of a function) is accessible by all functions within that module. However, it is not accessible by functions from other modules. static members exist as members of the class rather than as an instance in each object of the class.
Class variables are also known as static variables, and they are declared outside a method, with the help of the keyword 'static'. Static variable is the one that is common to all the instances of the class. A single copy of the variable is shared among all objects.
You are right in saying that the class can't be instantiated, but the class will exist within the application.
Therefore, only the first time the property is accessed, will the method GetStringFromSomeProcess
be called. Every other time after that, the check for == null
will resolve to false
and the value evaluated by the first call will be returned.
This will work fine - there is only one instance of theAnswer
because it is static - and (also because it is static) it can be accessed from a public static property. This means that any changes made to it will be visible to all code that accesses it. So the first call to GetString
will set theAnswer
to non-null, and subsequent calls will not make a call to GetStringFromSomeProcess()
.
However, the solution you posted is not threadsafe because GoGetTheAnswerFromALongRunningProcess()
could be called simultaneously by multiple threads.
.Net provides the Lazy
class to solve this issue, as follows:
public static class GetStringFromSomeProcess
{
private static readonly Lazy<string> _theAnswer = new Lazy<string>(GoGetTheAnswerFromALongRunningProcess);
public static string GetString
{
get
{
return _theAnswer.Value;
}
}
public static string GoGetTheAnswerFromALongRunningProcess()
{
return "X";
}
}
You supply to the constructor of the Lazy<T>
class a method that it can call when needed in order to create the object that it is wrapping. In the example above, I pass GoGetTheAnswerFromALongRunningProcess
to its constructor.
Also note that it's usually a bad idea to have a property that can take a very long time to return. It's better to make it a method:
public static string GetString()
{
return _theAnswer.Value;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With