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