C#特性之通俗演義

? 首先要說的是,可能一些剛接觸C#的朋友常常容易把屬性(Property)跟特性(Attribute)弄混淆,其實這是兩種不同的東西。屬性就是面向對象思想里所說的封裝在類里面的數據字段,其形式為:

?

????public?class?HumanBase
????{
????????
public?String?Name?{?get;?set;?}
????????
public?int?Age?{?get;?set;?}
????????
public?int?Gender?{?get;?set;?}
????}

?

?

在HumanBase這個類里出現的字段都叫屬性(Property),而C#特性(Attribute)又是怎樣的呢?

?

????[Serializable]
????
public?class?HumanBase
????{
????????
public?String?Name?{?get;?set;?}
????????
public?int?Age?{?get;?set;?}
????????
public?int?Gender?{?get;?set;?}
????}

?

?

??? 簡單地講,我們在HumanBase類聲明的上一行加了一個[Serializable],這就是特性(Attribute),它表示HumanBase是可以被序列化的,這對于網絡傳輸是很重要的,不過你不用擔心如何去理解它,如何理解就是我們下面要探討的。

?

??? C#特性可以應用于各種類型和成員。前面的例子將特性用在類上就可以被稱之為“類特性”,同理,如果是加在方法聲明前面的就叫方法特性。無論它們被用在哪里,無論它們之間有什么區別,特性的最主要目的就是自描述。并且因為特性是可以由自己定制的,而不僅僅局限于.NET提供的那幾個現成的,因此給 C#程序開發帶來了相當大的靈活性和便利。

我們還是借用生活中的例子來介紹C#的特性機制吧。

?

??? 假設有一天你去坐飛機,你就必須提前去機場登機處換登機牌。登機牌就是一張紙,上面寫著哪趟航班、由哪里飛往哪里以及你的名字、座位號等等信息,其實,這就是特性。它不需要你生理上包含這些屬性(人類出現那會兒還沒飛機呢),就像上面的HumanBase類沒有IsSerializable這樣的屬性,特性只需要在類或方法需要的時候加上去就行了,就像你不總是在天上飛一樣。

當我們想知道HumanBase是不是可序列化的,可以通過:

?

????????protected?void?Page_Load(object?sender,?EventArgs?e)
????????{
????????????Response.Write(
typeof(HumanBase).IsSerializable);
????????}

?

?

??? 拿到了登機牌,就意味著你可以合法地登機起飛了。但此時你還不知道你要坐的飛機停在哪里,不用擔心,地勤人員會開車送你過去,但是他怎么知道你是哪趟航班的呢?顯然還是通過你手中的登機牌。所以,特性最大的特點就是自描述。

既然是起到描述的作用,那目的就是在于限定。就好比地勤不會把你隨便拉到一架飛機跟前就扔上去了事,因為標簽上的說明信息就是起到限定的作用,限定了目的地、乘客和航班,任何差錯都被視為異常。如果前面的HumanBase不加上Serializable特性就不能在網絡上傳輸。

我們在順帶來介紹一下方法特性,先給HumanProperty加上一個Run方法:

?

ExpandedBlockStart.gif代碼
?[Serializable]
????
public?class?HumanPropertyBase
????{
????????
public?string?Name?{?get;?set;?}
????????
public?int?Age?{?get;?set;?}
????????
public?int?Gender?{?get;?set;?}
????????
public?void?Run(int?speed)
????????{?
???????????
//?Running?is?good?for?helath;
????????}
????}

?

?

??????? 只要是個四肢健全、身體健康的人就可以跑步,那這么說,跑步就是有前提條件的,至少是四肢健全,身體健康。由此可見,殘疾人和老年人如果跑步就會出問題。假設一個HumanBase的對象代表的是一位耄耋老人,如果讓他當劉翔的陪練,那就直接光榮了。如何避免這樣的情況呢,我們可以在Run方法中加一段邏輯代碼,先判斷Age大小,如果小于2或大于60直接拋異常,但是2-60歲之間也得用Switch來分年齡階段地判斷speed參數是否合適,那么邏輯就相當臃腫。簡而言之,如何用特性表示一個方法不能被使用呢?OK, here we go:

?

ExpandedBlockStart.gif代碼
?[Obsolete("I'm?so?old,don't?kill?me!",?true)]?//標記不再使用的程序元素。無法繼承此類。該布爾值指示是否將使用已過時的元素視為錯誤。
????????public?virtual?void?Run(int?speed)
????????{?
???????????
//?Running?is?good?for?helath;
????????}

?

?

??? 上面大致介紹了一下特性的使用與作用,接下來我們要向大家展示的是如何通過自定義特性來提高程序的靈活性,如果特性機制僅僅能使用.NET提供的那幾種特性,不就太不過癮了么。

首先,特性也是類。不同于其它類的是,特性都必須繼承自System.Attribute類,否則編譯器如何知道誰是特性誰是普通類呢。當編譯器檢測到一個類是特性的時候,它會識別出其中的信息并存放在元數據當中,僅此而已,編譯器并不關心特性說了些什么,特性也不會對編譯器起到任何作用,正如航空公司并不關心每個箱子要去哪里,只有箱子的主人和搬運工才會去關心這些細節。假設我們現在就是航空公司的管理人員,需要設計出前面提到的登機牌,那么很簡單,我們先看看最主要的信息有哪些:

?

ExpandedBlockStart.gif代碼
????public?class?BoardingCheckAttribute:System.Attribute
????{
????????
public?string?ID
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?string?Name
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?int?FlightNumber
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?int?PositionNumber
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?string?Departure
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?string?Destination
????????{
????????????
get;
????????????
private?set;
????????}
????}

?

?

??? 我們簡單列舉這些屬性作為航空公司登機牌上的信息,用法和前面的一樣,貼到HumanBase上就行了,說明此人具備登機資格。這里要簡單提一下,你可能已經注意到了,在使用BoardingCheckAttribute的時候已經把Attribute省略掉了,不用擔心,這樣做是對的,因為編譯器默認會自己加上然后查找這個屬性類的。哦,等一下,我突然想起來他該登哪架飛機呢?顯然,在這種需求下,我們的特性還沒有起到應有的作用,我們還的做點兒工作,否則乘客面對一張空白的機票一定會很迷茫。

?

?? 于是,我們必須給這個C#特性加上構造函數,因為它不僅僅表示登機的資格,還必須包含一些必要的信息才行:

?

ExpandedBlockStart.gif代碼
??public?BoardingCheckAttribute(string?id,string?name,int?flightNumber,int?positionNumber,string?departure,string?destination)
????????{
????????????
this.ID?=?id;
????????????
this.Name?=?name;
????????????
this.FlightNumber?=?flightNumber;
????????????
this.PositionNumber?=?positionNumber;
????????????
this.Departure?=departure;
????????????
this.Destination?=?destination;
????????}

?

?OK,我們的乘客就可以拿到一張正式的登機牌登機了,have a good flight!

?

ExpandedBlockStart.gif代碼
????[BoardingCheck("11","張三",1001,2002,"杭州","臺灣")]
????
public?class?HumanPropertyBase
????{
????????
public?string?Name?{?get;?set;?}
????????
public?int?Age?{?get;?set;?}
????????
public?int?Gender?{?get;?set;?}

????}

????
public?class?BoardingCheckAttribute:System.Attribute
????{

????????
public?BoardingCheckAttribute(string?id,string?name,int?flightNumber,int?positionNumber,string?departure,string?destination)
????????{
????????????
this.ID?=?id;
????????????
this.Name?=?name;
????????????
this.FlightNumber?=?flightNumber;
????????????
this.PositionNumber?=?positionNumber;
????????????
this.Departure?=departure;
????????????
this.Destination?=?destination;
????????}

????????
public?string?ID
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?string?Name
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?int?FlightNumber
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?int?PositionNumber
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?string?Departure
????????{
????????????
get;
????????????
private?set;
????????}

????????
public?string?Destination
????????{
????????????
get;
????????????
private?set;
????????}
????}

????
public?partial?class?WebForm1?:?System.Web.UI.Page
????{
????????
protected?void?Page_Load(object?sender,?EventArgs?e)
????????{
????????????BoardingCheckAttribute?boradingCheck?
=?null;

????????????
object[]?customAttributes?=?typeof(HumanPropertyBase).GetCustomAttributes(true);

????????????
foreach?(var?attribute?in?customAttributes)
????????????{
????????????????
if?(attribute?is?BoardingCheckAttribute)
????????????????{
????????????????????boradingCheck?
=?attribute?as?BoardingCheckAttribute;

????????????????????Response.Write(boradingCheck.Name
+"'s?ID?is?"
?????????????????????
+boradingCheck.ID+",he/she?wants?to?"+
?????????????????????boradingCheck.Destination
+"?from?"+
?????????????????????boradingCheck.Departure
+"?by?the?plane?"
?????????????????????
+boradingCheck.FlightNumber+
?????????????????????
",his/her?position?is?"+boradingCheck.PositionNumber+"."
?????????????????????);
????????????????}
????????????}
????????}
????}

?

?

轉載于:https://www.cnblogs.com/jhxk/articles/1739249.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379230.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379230.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379230.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

棧應用_計算按運算符優先級分布的算式(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; LinkList.h LinkList.c LinkStack.h LinkStack.c 棧-線性表 main.c #include <stdio.h> #include "LinkStack.h"//該程序用棧來計算算式 /*比如&#xff1a;1*56/(5-3)…

php globals_PHP $ GLOBALS(超級全局變量),帶有示例

php globalsPHP $全球 (PHP $GLOBALS) PHP $GLOBALS is the only superglobal that does not begin with an underscore (_). It is an array that stores all the global scope variables. PHP $ GLOBALS是唯一不以下劃線( _ )開頭的超全局變量。 它是一個存儲所有全局范圍變量…

安裝部署項目(轉自)

1 新建安裝部署項目 打開VS&#xff0c;點擊新建項目&#xff0c;選擇&#xff1a;其他項目類型->安裝與部署->安裝向導(安裝項目也一樣)&#xff0c;然后點擊確定。 2 安裝向導 關閉后打開安裝向導&#xff0c;點擊下一步&#xff0c;或者直接點擊完成。 3 開始制作…

java.lang.ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver

更改jdk&#xff0c;版本過高的緣故&#xff0c;更改jdk為1.7版本

kotlin 查找id_Kotlin程序查找給定范圍內的素數

kotlin 查找idA prime number is a natural number that is greater than 1 and cannot be formed by multiplying two smaller natural numbers. 質數是大于1的自然數&#xff0c;不能通過將兩個較小的自然數相乘而形成。 Given a range start and end, we have to print al…

socket代碼

客戶端:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> int main(int argc,char *argv[]) {int sockfd,numbytes;char buf[100];struct sockaddr_in th…

棧應用_將算式轉成按運算符優先級分布(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; LinkList.h LinkList.c LinkStack.h LinkStack.c 棧-線性表 main.c #include <stdio.h> #include "LinkStack.h"/* 該程序將 正常的算式 轉換成按照運算符優先分布的算式…

課堂筆記(一)

1&#xff0c;怎樣查詢函數的用法 help(函數名) 2&#xff0c;表達式float(0b1100010101)float(0o1425)float(0x315)的結果是什么&#xff0c;并說明原因 True 浮點類型的數用二進制八進制十六進制的不同表達 3&#xff0c;oct()方法 轉換八進制輸出 4&#xff0c;hex()方…

Struts2.0標簽使用之s:checkboxlist/

jsp代碼如下&#xff1a; <s:form action"receive.action" method"post"> <s:checkboxlist id"user" name"cheuser" list"#request.userlist" listKey"id" listValue"name" lab…

[轉]深入淺出Java設計模式之備忘錄模式

本文轉自&#xff1a;http://dev.yesky.com/450/2070450.shtml 一、引子   俗話說&#xff1a;世上難買后悔藥。所以凡事講究個“三思而后行”&#xff0c;但總常見有人做“痛心疾首”狀&#xff1a;當初我要是……。如果真的有《大話西游》中能時光倒流的“月光寶盒”&#…

遞歸問題(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; main.c #include <stdio.h>//該程序使用遞歸將字符串從后往前依次輸出void reverse(char* s) {if( (s ! NULL) && (*s ! \0) ){reverse(s 1);printf("%c", *s);…

Java LocalDate類| ofYearDay()方法與示例

LocalDate類的YearDay()方法 (LocalDate Class ofYearDay() method) ofYearDay() method is available in java.time package. ofYearDay()方法在java.time包中可用。 ofYearDay() method is used to create an instance of LocalDate object that holds the value from the ye…

ASP.NET C#讀寫Cookie的方法!

Cookie (HttpCookie的實例)提供了一種在 Web 應用程序中存儲用戶特定信息的方法。例如&#xff0c;當用戶訪問您的站點時&#xff0c;您可以使用 Cookie 存儲用戶首選項或其他信息。當該用戶再次訪問您的網站時&#xff0c;應用程序便可以檢索以前存儲的信息。 創建Cookie方法…

遞歸-裴波那契數列(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; main.c #include <stdio.h>//該程序輸出裴波那契數列 int fibonacci(int n) {if( n > 1 ){return fibonacci(n-1) fibonacci(n-2);//注意&#xff1a;這里調用是一直調用左邊函…

javascript 事件委派

javascript 模擬用戶操作 <a href"javascript:;" onClick"javascript:alert(131231);" id"abc">asdfasdf</a> <script> if(document.all) { document.getElementById(abc).fireEvent(onclick); } else { var evt document.cr…

Java Duration類| isNegative()方法與示例

持續時間類isNegative()方法 (Duration Class isNegative() method) isNegative() method is available in java.time package. isNegative()方法在java.time包中可用。 isNegative() method is used to check whether this Duration object holds the value of length < 0 …

經典例題(一)

1&#xff0c;已知復數 x 6 8j 請寫出它的模、實部、虛部及共軛復數的命令&#xff0c;并寫出運行結果。 X 6 8j print("模為:%d"% abs(X)) print("實部為:%s"% X.real) print("虛部為:%s"% X.imag) print("共軛復數為:%s"% X.co…

asterisk撥號規則

一、前言 本文檔以asterisk-1.4.32為基礎寫作而成&#xff0c;可能和其他版本有些區別。其中參考了一些別的書籍和文章。因為寫的比較倉促&#xff0c;而且基本都是晚上寫的&#xff0c;里面的內容邏輯性和語句沒有仔細斟酌&#xff0c;就是想到什么寫什么&#xff0c;難免有…

getseconds補0_Java Duration類| getSeconds()方法與示例

getseconds補0持續時間類getSeconds()方法 (Duration Class getSeconds() method) getSeconds() method is available in java.time package. getSeconds()方法在java.time包中可用。 getSeconds() method is used to return the number of seconds exists in this Duration. g…

遞歸-漢諾塔(代碼、分析、匯編)

代碼&#xff1a; #include <stdio.h>void hanoi(int n, char a, char b, char c) {if( n > 0 ){if( n 1 ){printf("%c -> %c\n", a, c);}else{hanoi(n-1, a, c, b);printf("%c -> %c\n", a, c);hanoi(n-1, b, a, c);}} }int main() {han…