静态成员变量是否可以用于缓存静态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提供了Lazyclass来解决这个问题,如下:

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;
        }
    }
}