簡體   English   中英

C# - 每次訪問屬性時都會重新計算屬性嗎?

[英]C# - Are properties recalculated everytime they are accessed?

假設以下簡單代碼:

private const int A = 2;
private const int B = 3;


public int Result
    {
        get
        {
            return A * B;
        }
    }

我很多次使用Result屬性。
每次都會重新計算產品A * B嗎?

如果您不將值存儲在私有字段中,那么它將在每次訪問時重新計算。

緩存結果的方法是

private int? _result;
public int Result {
  get {
     if (!_result.HasValue) {
       _result = A*B;
     }
     return _result.Value;
  }
}

這里有幾點需要注意。

首先 ,如果所有操作都是針對常量的,那么編譯器會自動為您優化這些操作。 這意味着乘法操作實際上不會在運行時執行。 這意味着你不應該擔心它。

其次 ,如果操作僅限於對兩個現有變量執行簡單的算術運算,那么每次計算它將比上面的“if”測試更快。 此外,在這種情況下,帶有私有字段的本地存儲會增加內存占用,這是沒有用的原因。

第三 ,如果底層變量在對屬性getter的調用之間發生了變化 (即A或B有一個新值),那么這將不會重新計算這些新值。

這使得我們實際使用上述代碼的原因之一是:操作需要很長時間,並且操作的數據在對屬性的調用之間不會發生變化。 我現在想到的另一個原因就是如果屬性是一個必須在調用之前被實例化的對象。

屬性並不神奇。 它們只是兩種方法的語法糖, get_Xxxset_Xxx 知道這一點,很明顯每次訪問屬性時, get部分內的所有代碼都會被執行。

由於值是const ,編譯器可能會優化這種情況。

但如果它們不是const ,則每次都會計算出來。

是。 但是,一個好的經驗法則是,如果你想要這樣的操作,它應該是一種方法。

是的,屬性只是每次訪問時執行的特殊方法。 如果要緩存結果,請將其存儲在成員變量(可能是可空的int)中,並在返回之前檢查它是否已經計算(也稱為延遲初始化):

int? _result = null;
public int Result {
    get {
        if ( _result == null )
            _result = A * B;
        return _result;
    }
}

大多數語言都沒有定義優化的工作方式。 通常的語言 - 律師短語“似乎”,在這種情況下,C#定義很可能會說“每次調用時屬性的值都被返回,就像它被評估一樣”。 這使編譯器類型可以自由地執行任何保留記錄行為的操作。

因此,編譯器可能會對此進行優化。 通常,具有悠久歷史和強調性能的編譯器(C#具有悠久的歷史和大量資源,而不是如此強調性能)試圖弄清楚在什么情況下可以重用先前計算的結果。 你的A和B被聲明為CONSTS的事實表明編譯器可以發現產品是一個常量,實際上它可以用const替換getter上的每個調用。

它可以。 它是否是一個懸而未決的問題。 我懷疑微軟會以“是的絕對做到這一點”的方式回答這個問題。

每次調用該屬性時都會對其進行評估。 如果你想要更高效的東西,你必須自己處理它。

在反射器中打開程序集,編譯器將優化乘法,因為它們是const int

public class FooContainer
{
    private const int A = 2;
    private const int B = 3;


    public int Result
    {
        get
        {
            return A * B;
        }
    }
}

會變成:

public class FooContainer
{
    // Fields
    private const int A = 2;
    private const int B = 3;

    // Properties
    public int Result
    {
        get
        {
            return 6;
        }
    }
}

但是,如果將變量更改為int並且不存儲計算,則每次都會進行評估。

例:

public class FooContainer
{
    private int A = 2;
    private const int B = 3;


    public int Result
    {
        get
        {
            return A * B;
        }
    }
}

變為:

public class FooContainer
{
    // Fields
    private int A = 2;
    private const int B = 3;

    // Properties
    public int Result
    {
        get
        {
            return (this.A * 3);
        }
    }
}

暫無
暫無

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

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