我遇到过这段代码,看起来原始开发人员试图使用静态字符串来缓存静态类中的值。
public static class GetStringFromSomeProcess
{
private static string theAnswer;
public static string GetString
{
get
{
if(theAnswer == null)
{
theAnswer = GoGetTheAnswerFromALongRunningProcess();
}
return theAnswer;
}
}
}
据我所知,这不起作用,因为您无法实例化GetStringFromSomeProcess
类,每次使用GoGetTheAnswerFromALongRunningProcess
时都会调用GetString
。我错过了什么吗?
答案 0 :(得分:3)
你说的是,这个类不能被实例化,但是该类将存在于应用程序中。
因此,只有第一次访问该属性时,才会调用方法GetStringFromSomeProcess
。在此之后的每隔一段时间,== null
的检查将解析为false
,并且将返回第一次通话评估的值。
答案 1 :(得分:3)
这样可以正常工作 - theAnswer
只有一个实例,因为它是静态的 - 并且(也因为它是静态的)可以从公共静态属性访问它。这意味着对其进行的任何更改都将对访问它的所有代码可见。因此,第一次调用GetString
会将theAnswer
设置为非空,后续调用将不会调用GetStringFromSomeProcess()
。
但是,您发布的解决方案不是线程安全的,因为多个线程可以同时调用GoGetTheAnswerFromALongRunningProcess()
。
.Net提供Lazy
类来解决此问题,如下所示:
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";
}
}
您向Lazy<T>
类的构造函数提供了一个方法,它可以在需要时调用它以创建它正在包装的对象。在上面的示例中,我将GoGetTheAnswerFromALongRunningProcess
传递给它的构造函数。
另请注意,拥有一个可能需要很长时间才能返回的属性通常是一个坏主意。最好把它变成一种方法:
public static string GetString()
{
return _theAnswer.Value;
}
答案 2 :(得分:0)
如果没有创建GetStringFromSomeProces类的对象,它是否正常工作?由于字符串theAnswer也是静态的,它可能有效,但我想知道该变量何时初始化。通常,您会像使用GetStringFromSomeProcess类的初始化建议一样对其进行编码。
Main.cs
...
GetStringFromSomeProcess getString = new GetStringFromSomeProcess();
string answer = getString.theAnswer();
...
<强> GetStringFromSomeProcess.cs 强>
public class GetStringFromSomeProcess
{
private string _theAnswer;
public string theAnswer
{
get
{
if(theAnswer == null)
{
GoGetTheAnswerFromALongRunningProcess getAnswer = new GoGetTheAnswerFromALongRunningProcess();
_theAnswer = getAnswer.GetAnswer();
}
return _theAnswer;
}
}
}