簡體   English   中英

可以使用靜態成員變量來緩存靜態類中的值嗎?

[英]Can a static member variable be used 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;
        }
    }
}   

據我所知,這不起作用,因為你無法實例化GetStringFromSomeProcess類,每次使用GetString都會調用GoGetTheAnswerFromALongRunningProcess 我錯過了什么嗎?

你說的是無法實例化類,但是該類將存在於應用程序中。

因此,只有第一次訪問屬性時,才會調用GetStringFromSomeProcess方法。 在此之后的每隔一段時間,檢查== null將解析為false並返回第一次調用評估的值。

這樣可以正常工作 - 只有一個theAnswer實例,因為它是靜態的 - 並且(因為它是靜態的)它可以從公共靜態屬性訪問。 這意味着對其進行的任何更改都將對訪問它的所有代碼可見。 因此,第一次調用GetString會將theAnswer設置為非null,后續調用將不會調用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;
}

沒有創建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;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM