C#無參屬性

來源:互聯網
上載者:User

大家來討論下C#無參屬性這個東西到底有沒有存在的必要?

永遠不要公開類型的欄位,物件導向設計和編程的重要原則之一就是 資料封裝。如果公開類型的欄位,會很容易的寫出不恰當使用欄位的代碼。這裡可以把欄位聲明為private,然後聲明訪問器方法。

    class test
{

private string Name;
public void SetName(string value)
{
Name = value;
}
public string GetName()
{
return Name;
}

}

實現唯讀或唯寫就是這麼簡單,不實現一個索引器方法就行了。還可以將Setname方法標記為protected,就可以只允許衍生類別修改了。聰明的你也發現上面這個做法的缺點了吧,首先得去實現額外的方法,所以會產生更多的代碼,其次,如果調用的時候必須調用方法,不能直接引用一個欄位名。還好C#給我們提供了一個稱為屬性(property)的機制,它緩解了第一個缺點造成的影響,也消除了第二個缺點。

   class test
{

private string name;
public string Name {
get { return name; }
set { if ("狗剩" == value) { Console.WriteLine("系統崩潰,拋出異常"); return; } name = value; }
}

}

屬性可以用任意的可存取修飾詞來標記。不能定義名稱相同的屬性。

如果只是為了封裝一個支援欄位而建立屬性,C#還提供一一種更簡單的文法,稱為自動實作屬性(Automatically Implemented Property,簡稱AIP)。like this

   class test
{
public int Age
{
get;
set;
}
}

如果聲明一個屬性而不提供get/set實現,C#會自動為你聲明一個私人欄位。原始代碼是這樣的:

public int Age
{
[CompilerGenerated]
get
{
int num;
num = this.<Age>k__BackingField;
Label_0009:
return num;
}
[CompilerGenerated]
set
{
this.<Age>k__BackingField = value;
return;
}
}

和直接聲明一個public 的Age欄位相比,自動實作屬性的優勢在哪?兩者存在一處重要的區別:使用自動實作屬性(AIP)意味著已經建立一個屬性,訪問該屬性的時候會調用get/set方法。如果有一天你決定自己實現這個AIP的get/set,而不接受編譯器預設的實現,那麼訪問這個屬性的任何代碼都不必重新編譯。如果是一個public的Age欄位,如果你把它更改為屬性,那麼訪問這個欄位的所有代碼就都需要重新編譯了。

凡事都有好有壞,那麼AIP有哪些不討人喜歡的地方呢:

1.如果使用欄位聲明的文法,可以包含初始化的部分,如果使用AIP就不行了,必須在咩個構造器中顯示的初始化每個AIP。

2.AIP支援的欄位名是由編譯器決定的,而且每次重新編譯,這個欄位名可能會發生更改,這樣一來,只要含有一個AIP就不能對類型的執行個體進行還原序列化了。在任何想要序列化或還原序列化的類型中,都不要使用AIP功能。

3.不能在AIP的get/set添加斷點,所以不好檢測程式在什麼時候擷取或設定這個屬性。咱手動實現的就可以設定斷點,不信你試試。

AIP功能是作用於整個屬性的:要麼都用,要麼都不用,這意味這,如果顯式的實現get那麼set也要顯式實現,反之亦然。

 

屬性看起來與欄位相似,但本質上是方法。屬性與欄位的區別如下:

1.屬性可以是唯讀或唯寫的(get/set訪問器方法),欄位卻總是可讀可寫的。

2.屬性方法可能拋出異常,欄位訪問不會拋出。

3.屬性不能作為out或ref參數傳遞給方法,欄位可以。

class Program
{
public int Age
{
get {return 3 ;}
set{}
}
int age;
static void Main()
{
var t = new { name="XiaoBai",age=22 };
test tt = new test();
//tt.Name = "狗剩";
Program p = new Program();
some(out p.age);
some(out p.Age);//屬性,索引器或動態成員不得作為out或ref參數傳遞
Console.ReadKey();
}
static void some(out int age)
{
age = 10;
}
}

4.屬性方法可能花費較長時間執行,欄位的訪問都是立即完成。

5.屬性方法可能需要額外的記憶體,或者返回一個不正確的引用,指向不屬於對象狀態一部分的某個東西,這樣一來,對返回對象的修改就作用不到原始對象身上了,相反查詢欄位返回的總是正確的引用,它指向的東西保證是原始對象狀態的一部分。使用會返回一個拷貝的屬性時,非常容易引起混淆。

如果仔細研究下屬性和欄位的差別,你會發現只有在極個別的情況下屬性才真正有用。屬性唯一的好處就是提供了簡化的文法,和調用普通方法(非屬性中的方法)相比,屬性不僅不會提升代碼的效能,還會妨礙對代碼的理解。

屬性訪問器的可訪問性:

我們有時希望為get訪問器指定一種可訪問性,為set訪問器指定另一種訪問器:

    class test
{
public int Age
{
get { return age; }
protected set { if (value < 0) Console.WriteLine("年齡錯誤!"); else { age = value; } }
}
int age;
}

如上所述,Age屬性本身聲明為public,意味這get訪問器方法是公用的,可由所有代碼訪問,但是,注意set訪問器方法被聲明為protected,只能從test的內部定義的代碼中調用,或者從test的衍生類別的代碼中調用。

定義一個屬性時,如果兩個訪問其方法需要具有不同的可訪問性,C#文法要求必須為屬性本身指定限制最不大的那一種可訪問性,然後在兩個訪問其中,只能選擇一個來應用限制較大的那一種可訪問性。在前面的例子中,屬性本身為public,set訪問器為protected(限制比public大)。

   class test
{
private int Age
{
get { return age; }
protected set { if (value < 0) Console.WriteLine("年齡錯誤!"); else { age = value; } }//這裡就通不過編譯
}
int age;
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.