静态成员变量可以用于缓存静态类中的值吗?

jon*_*lon 5 c# static-methods caching

我遇到过这段代码,看起来原始开发人员试图使用静态字符串来缓存静态类中的值。

public static class GetStringFromSomeProcess
{
    private static string theAnswer;

    public static string GetString
    {
        get
        {
            if(theAnswer == null)
            {
                theAnswer = GoGetTheAnswerFromALongRunningProcess();
            }
            return theAnswer;
        }
    }
}   
Run Code Online (Sandbox Code Playgroud)

据我所知,这是行不通的,因为您无法实例化GetStringFromSomeProcess该类,GoGetTheAnswerFromALongRunningProcess每次使用时都会被调用GetString。我错过了什么吗?

Mat*_*son 8

这将工作正常 - 只有一个实例,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";
    }
}
Run Code Online (Sandbox Code Playgroud)

您向类的构造函数提供Lazy<T>一个方法,它可以在需要时调用该方法来创建它所包装的对象。在上面的示例中,我传递GoGetTheAnswerFromALongRunningProcess给它的构造函数。

另请注意,拥有需要很长时间才能归还的房产通常不是一个好主意。最好将其设为一种方法:

public static string GetString()
{
    return _theAnswer.Value;
}
Run Code Online (Sandbox Code Playgroud)