簡體   English   中英

為什么要為屬性創建私有字段?

[英]Why create private fields for properties?

我一直在研究與字段相比的屬性示例,而我總是不加解釋地看到的一件事是創建一個私有字段,然后創建一個屬性。 為什么我們需要_foo ,而不能只運行類似於下面的代碼,或者用Foo = value代替Foo = Foo

我在運行它時看到它創建了一個堆棧溢出異常,所以我猜想它正在尋找一個值來填充Foovalue ,但是我認為當我執行def.Foo = 55時可以處理該def.Foo = 55

即使創建私有字段是最佳實踐,我仍然想更好地了解導致溢出的實際原因。

class ABC
{
    private int _foo; //Why create this?
    public int Foo
    {
        get { return Foo; }
        set
        {
            Foo = Foo;//more logic would go here. }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        ABC def = new ABC();
        def.Foo = 55;
        Console.WriteLine($"The value of Foo is {def.Foo}.");
        Console.ReadLine();
    }
}

這是因為字段屬性不相同。

private int _foo; //field
public int Foo //property
{
    get { return _foo; } //should be _foo
    set
    {
        _foo = value;
    }
}

通常,您使用公共屬性來訪問私有字段,因為除了分配/獲取字段的值之外,您可能還想做其他事情。

例:

private bool selectedIndexChanged; //note this additional field
public bool SelectedIndexChanged {
    get { return selectedIndexChanged; }
    set { selectedIndexChanged = value; }
}

private int selectedIndex; //Why create this?
public int SelectedIndex
{
    get { return selectedIndex; }
    set
    {
        selectedIndexChanged = value != selectedIndex; //you update selectedIndexChanged here!
        selectedIndex = value;
    }
}

請注意,您沒有直接訪問私有字段,而是通過公共屬性訪問它們。 具有屬性的好處是,您不僅可以讀取/分配字段值,還可以執行其他操作 :檢查輸入的有效性,分配其他字段,調用事件等。

即使創建私有字段是最佳實踐,我仍然想更好地了解導致溢出的實際原因。

溢出不是最佳實踐引起的,而是由錯誤的實踐引起的:

private int _foo; //Why create this?
public int Foo
{
    get { return Foo; } //this should not happen, wrong practice
    set
    {
        Foo = Foo; //neither should this happen, another wrong practice
    }
}

上面的代碼中發生的是:

  1. 您得到Foo,返回Foo,您需要得到Foo,這需要Foo,它需要返回Foo,需要得到Foo,然后返回Foo,您需要得到Foo,返回Foo,需要得到Foo的返回Foo,您需要獲取Foo,然后返回Foo,您需要獲取Foo。Foo,您需要獲取Foo,您需要獲取Foo,您需要獲取Foo,返回Foo,您需要獲取Foo,您需要獲取Foo,這需要返回Foo。您需要獲得Foo的返還Foo,需要獲得Foo的返還Foo,需要獲得Foo的返還Foo,需要獲得Foo的返還Foo,需要獲得Foo的返還Foo,需要獲得Foo的返還Foo,需要的要獲取Foo,返回Foo,您需要獲取Foo,返回Foo,您需要獲取Foo,需要返回Foo,您需要獲取Foo,返回Foo,您需要獲取Foo,需要返回Foo,您需要獲取Foo Foo返回Foo,您需要獲取Foo ...直到無窮大

同樣:

  1. 您設置了Foo,需要獲取Foo,然后返回Foo,您需要獲取Foo,然后您需要獲取Foo,這需要返回Foo,您需要獲取Foo,然后返回Foo,您需要獲取Foo,然后返回Foo,您需要返回Foo要獲得Foo返還Foo,您需要獲得Foo,這需要返還Foo,您需要獲得Foo返還Foo,您需要獲得Foo,這需要返還Foo,您需要獲得Foo返還Foo,您需要獲取Foo ,返回Foo,您需要獲取Foo,返回Foo,您需要獲取Foo,返回Foo,您需要獲取Foo,然后返回Foo,您需要獲取Foo,返回Foo,您需要獲取Foo,然后返回Foo, ,您需要獲取Foo,然后返回Foo,然后返回Foo,然后返回Foo,您需要獲取Foo,然后返回Foo,您需要獲取Foo,然后返回Foo,返回Foo,您需要獲取Foo,然后返回Foo,你需要讓Foo返回Foo,而你需要讓Foo ...直到無窮大

從而導致溢出...

為什么我們需要_foo,而不能僅僅運行類似於我下面的代碼,或者替換掉?

因為屬性是設置或獲取字段值的方法。 因此,您必須先定義一個字段。 如果您必須暗示內部特別是設置程序中的任何邏輯,則這是必需的。 否則,更常見的是使用自動實現的屬性。

即使在使用自動實現的屬性的情況下,編譯器也會為我們生成一個后備字段。

public Person
{
    public string FirstName { get; set; }
}

例如,這樣做

var person = new Person { FirstName = "Bob" };

您創建一個新的Person對象,其屬性名為FirstName ,其類型為string。 此外,您將人員的FirstName為Bob。 這是您必須注意的一點。 編譯器將生成一個字符串類型的后備字段,並且在運行時將在此處存儲對人的名字的引用。

上面的類的定義類似於以下定義:

public Person
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }
}

實際上,這就是定義自動實現的屬性時,后台編譯器的作用。 基於此,我們可以說對字符串“ Bob”的引用將存儲到_firstName

屬性實際上是實際變量的獲取/設置方法。 但是,您並不總是需要擁有私有變量才能擁有屬性。

你可以簡單地擁有

public int Foo { get; set; }

編譯器將為您創建和設置變量。 但是,如果需要限制屬性以免分配錯誤的值或執行一些其他任務,則需要屬性變量。

例:

private int _score;
public int Score
{
    get { return _score; }
    set
    {
        if(value > 100)
            throw new Exception("Score cannot be more than 100");

        _score = value;
    }
}

暫無
暫無

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

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