亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#中Property和Attribute的區別實例詳解

2020-01-24 01:48:33
字體:
來源:轉載
供稿:網友

本文實例分析了C#中Property和Attribute的區別。分享給大家供大家參考。具體分析如下:

在C#中有兩個屬性,分別為Property和Attribute,兩個的中文意思都有特性、屬性之間,但是用法上卻不一樣,為了區別,本文暫把Property稱為特性,把Attribute稱為屬性。

Attribute才是本文的主角,把它稱為屬性我覺得很恰當。屬性的意思就是附屬于某種事物上的,用來說明這個事物的各種特征的一種描述。而Attribute就是干這事的。它允許你將信息與你定義的C#類型相關聯,作為類型的標注。這些信息是任意的,就是說,它不是由語言本身決定的,你可以隨意建立和關聯任何類型的任何信息。你可以作用屬性定義設計時信息和運行時信息,甚至是運行時的行為特征。關鍵在于這些信息不僅可以被用戶取出來作為一種類型的標注,它更可以被編譯器所識別,作為編譯時的一種附屬條件參加程序的編譯。

以下部分內容及代碼來源于《C#技術揭秘》(Inside C# Sencond Edition)

定義屬性:

屬性實際上是一個派生自System.Attribute基類的類。System.Attribute類含有幾個用于訪問和檢查自定義屬性的方法。盡管你有權將任何類定義為屬性,但是按照慣例來說,從System.Attribute派生類是有意義的。示例如下:

public enum RegHives{   HKEY_CLASSES_ROOT,   HKEY_CURRENT_USER,   HKEY_LOCAL_MACHINE,   HKEY_USERS,   HKEY_CURRENT_CONFIG}public class RegKeyAttribute : Attribute{   public RegKeyAttribute(RegHives Hive, String ValueName)   {    this.Hive = Hive;    this.ValueName = ValueName;   }   protected RegHives hive;   public RegHives Hive   {    get { return hive; }    set { hive = value; }   }   protected String valueName;   public String ValueName   {    get { return valueName; }    set { valueName = value; }   }}

我們在這里添加了不同注冊表的枚舉、屬性類的構造器以及兩個特性(Property)。在定義屬性時你可以做許許多多的事情,下面我們看看如何在運行時查詢屬性。要想在運行時查詢類型或成員所附著的屬性,必須使用反射

查詢類屬性:

假設你希望定義一個屬性,這個屬性定義了將在其上創建對象的遠程服務器。如果沒有這個屬性,就要把此信息保存在一個常量中或是一個應用程序的資源文件中。通過使用屬性,只需用以下方法標注出類的遠程服務器名即可:

using System;namespace QueryAttribs{  public enum RemoteServers  {   JEANVALJEAN,   JAVERT,   COSETTE   }  public class RemoteObjectAttribute : Attribute  {   public RemoteObjectAttribute(RemoteServers Server)   {    this.server = Server;   }   protected RemoteServers server;   public string Server   {    get    {     return RemoteServers.GetName(      typeof(RemoteServers), this.server);    }   }  }  [RemoteObject(RemoteServers.COSETTE)]  class MyRemotableClass  {  }  class Test  {   [STAThread]   static void Main(string[] args)   {    Type type = typeof(MyRemotableClass);    foreach (Attribute attr in     type.GetCustomAttributes(true))    {     RemoteObjectAttribute remoteAttr =      attr as RemoteObjectAttribute;     if (null != remoteAttr)     {     Console.WriteLine(       "Create this object on {0}.",       remoteAttr.Server);     }    }    Console.ReadLine();   }  }}

運行結果為:

Creat this object on COSETTE。

注意:在這個例子中的屬性類名具有Attribute后綴。但是,當我們將此屬性附著給類型或成員時卻不包括Attribute后綴。這是C#語言的設計者提供的簡單方式。當編譯器看到一個屬性被附著給一個類型或成員時,它會搜索具有指定屬性名的System.Attribute派生類。如果編譯器沒有找到匹配的類,它就在指定的屬性名后面加上Attribute,然后再進行搜索。因此,常見的使用做法是將屬性類名定義為以Attribute結尾,在使用時忽略名稱的這一部分。以下的代碼都采用這種命名方式。

查詢方法屬性:

在下面這個例子中,我們使用屬性將方法定義為可事務化的方法,只要存在TransactionableAttribute屬性,代碼就知道具有這個屬性的方法可以屬于一個事務。

using System;using System.Reflection;namespace MethodAttribs{  public class TransactionableAttribute : Attribute  {   public TransactionableAttribute()   {   }  }  class SomeClass  {   [Transactionable]   public void Foo()   {}   public void Bar()   {}   [Transactionable]   public void Goo()   {}  }  class Test  {   [STAThread]   static void Main(string[] args)   {    Type type = Type.GetType("MethodAttribs.SomeClass");    foreach (MethodInfo method in type.GetMethods())    {     foreach (Attribute attr in      method.GetCustomAttributes(true))     {      if (attr is TransactionableAttribute)      {       Console.WriteLine(        "{0} is transactionable.",        method.Name);      }     }    }    Console.ReadLine();   }  }}

運行結果如下:

Foo is transactionable.
Goo is transactionable.
 
查詢字段屬性:

假設有一個類含有一些字段,我們希望將它們的值保存進注冊表。為此,可以使用以枚舉值和字符串為參數的構造器定義一個屬性,這個枚舉值代表正確的注冊表hive,字符串代表注冊表值名稱。在運行時可以查詢字段的注冊表鍵。

using System;using System.Reflection;namespace FieldAttribs{  public enum RegHives  {   HKEY_CLASSES_ROOT,   HKEY_CURRENT_USER,   HKEY_LOCAL_MACHINE,   HKEY_USERS,   HKEY_CURRENT_CONFIG  }  public class RegKeyAttribute : Attribute  {   public RegKeyAttribute(RegHives Hive, String ValueName)   {    this.Hive = Hive;    this.ValueName = ValueName;   }   protected RegHives hive;   public RegHives Hive   {    get { return hive; }    set { hive = value; }   }   protected String valueName;   public String ValueName   {    get { return valueName; }    set { valueName = value; }   }  }  class SomeClass  {   [RegKey(RegHives.HKEY_CURRENT_USER, "Foo")]   public int Foo;    public int Bar;  }  class Test  {   [STAThread]   static void Main(string[] args)   {    Type type = Type.GetType("FieldAttribs.SomeClass");    foreach (FieldInfo field in type.GetFields())    {     foreach (Attribute attr in      field.GetCustomAttributes(true))     {      RegKeyAttribute rka =       attr as RegKeyAttribute;      if (null != rka)      {       Console.WriteLine(        "{0} will be saved in"        + " {1}////{2}",        field.Name,        rka.Hive,        rka.ValueName);      }     }    }    Console.ReadLine();   }  }}

運行結果為:

Foo will be saved in HKEY_CURRENT_USER//Foo

大家可以看到,用屬性來標注類、方法、字段,既可以把用戶的自定義信息附屬在實體上,又可以在運行時動態的查詢。下面我將講一些C#中默認的預定義屬性,見下表:

預定義的屬性 有效目標 說明
AttributeUsage Class 指定另一個屬性類的有效使用方式
CLSCompliant 全部 指出程序元素是否與CLS兼容
Conditional Method 指出如果沒有定義相關聯的字符串,編譯器就可以忽略對這個方法的任何調用
DllImport Method 指定包含外部方法的實現的DLL位置
STAThread Method(Main) 指出程序的默認線程模型為STA
MTAThread Method(Main) 指出程序的默認模型為多線程(MTA)
Obsolete 除了Assembly、Module、Parameter和Return 將一個元素標示為不可用,通知用戶此元素將被從未來的產品
ParamArray Parameter 允許單個參數被隱式地當作params(數組)參數對待
Serializable Class、Struct、enum、delegate 指定這種類型的所有公共和私有字段可以被串行化
NonSerialized Field 應用于被標示為可串行化的類的字段,指出這些字段將不可被串行化
StructLayout Class、struct 指定類或結構的數據布局的性質,比如Auto、Explicit或sequential
ThreadStatic Field(靜態) 實現線程局部存儲(TLS)。不能跨多個線程共享給定的靜態字段,每個線程擁有這個靜態字段的副本

下面介紹幾種常用的屬性

1.[STAThread]和[MTAThread]屬性

class Class1{  [STAThread]  Static void Main( string[] args )  {  }}

使用STAThread屬性將程序的默認線程模型指定為單線程模型。注意,線程模型只影響使用COM interop的應用程序,將這個屬性應用于不使用COM interop的程序將不會產生任何效果。

2. AttributeUsage屬性

除了用于標注常規C#類型的自定義屬性以外,還可以使用AttributeUsage屬性定義你使用這些屬性的方式。文件記錄的AttributeUsage屬性調用用法如下:

[AttributeUsage( validon , AllowMutiple = allowmutiple , Inherited = inherited )]Validon參數是AttributeTargets類型的,這個枚舉值的定義如下:public enum AttributeTargets{  Assembly = 0x0001,  Module = 0x0002,  Class = 0x0004,  Struct = 0x0008,  Enum = 0x0010,  Constructor = 0x0020,  Method = 0x0040,  Property = 0x0080,  Field = 0x0100,  Event = 0x200,  Interface = 0x400,  Parameter = 0x800,  Delegate = 0x1000,  All = Assembly | Module | Class | Struct | Enum | Constructor| Method | Property|     Filed| Event| Interface | Parameter | Deleagte ,  ClassMembers = | Class | Struct | Enum | Constructor | Method | Property | Field |     Event | Delegate | Interface }

AllowMultiple決定了可以在單個字段上使用某個屬性多少次,在默認情況下,所有的屬性都是單次使用的。示例如下:

[AttributeUsage( AttributeTargets.All , AllowMultiple = true )]public class SomethingAttribute : Attribute{  public SomethingAttribute( string str )  {  }}//如果AllowMultiple = false , 此處會報錯[Something(“abc”)][Something(“def”)]class Myclass{}

Inherited參數是繼承的標志,它指出屬性是否可以被繼承。默認是false。
Inherited AllowMultiple 結果
true false 派生的屬性覆蓋基屬性
true false 派生的屬性和基屬性共存

代碼示例:

using System;using System.Reflection;namespace AttribInheritance{  [AttributeUsage(   AttributeTargets.All,   AllowMultiple=true,//  AllowMultiple=false,   Inherited=true  )]  public class SomethingAttribute : Attribute  {   private string name;   public string Name   {    get { return name; }    set { name = value; }   }   public SomethingAttribute(string str)   {    this.name = str;   }  }  [Something("abc")]  class MyClass  {  }  [Something("def")]  class Another : MyClass  {  }  class Test  {   [STAThread]   static void Main(string[] args)   {    Type type =     Type.GetType("AttribInheritance.Another");    foreach (Attribute attr in     type.GetCustomAttributes(true))//    type.GetCustomAttributes(false))    {     SomethingAttribute sa =      attr as SomethingAttribute;     if (null != sa)     {     Console.WriteLine(       "Custom Attribute: {0}",       sa.Name);     }    }    }  }}

當AllowMultiple被設置為false時,結果為:
Custom Attribute : def
當AllowMultiple被設置為true時,結果為:
Custom Attribute : def
Custom Attribute : abc

注意,如果將false傳遞給GetCustomAttributes,它不會搜索繼承樹,所以你只能得到派生的類屬性。
 
3.Conditional 屬性

你可以將這個屬性附著于方法,這樣當編譯器遇到對這個方法調用時,如果沒有定義對應的字符串值,編譯器就忽略這個調用。例如,以下方法是否被編譯取決于是否定義了字符串“DEGUG”:

[Condition(“DEBUG”) ]public void SomeDebugFunc(){  Console.WriteLine(“SomeDebugFunc”);}using System;using System.Diagnostics;namespace CondAttrib{  class Thing  {   private string name;   public Thing(string name)   {    this.name = name;    #if DEBUG     SomeDebugFunc();    #else     SomeFunc();    #endif   }   public void SomeFunc()    { Console.WriteLine("SomeFunc"); }   [Conditional("DEBUG")]   [Conditional("ANDREW")]   public void SomeDebugFunc()    { Console.WriteLine("SomeDebugFunc"); }  }  public class Class1  {   [STAThread]   static void Main(string[] args)   {    Thing t = new Thing("T1");   }  }}

4. Obsolete 屬性

隨著代碼不斷的發展,你很可以會有一些方法不用??梢詫⑺鼈兌紕h除,但是有時給它們加上適當的標注比刪除它們更合適,例如:

using System;namespace ObsAttrib{  class SomeClass  {   [Obsolete("Don't use OldFunc, use NewFunc instead", true)]   public void OldFunc( ) { Console.WriteLine("Oops"); }    public void NewFunc( ) { Console.WriteLine("Cool"); }  }  class Class1  {   [STAThread]   static void Main(string[] args)   {    SomeClass sc = new SomeClass();    sc.NewFunc();//   sc.OldFunc(); // compiler error   }  }}

我們將Obsolete屬性的第二個參數設置為true,當調用時函數時編譯器會產生一個錯誤。

E:/InsideC#/Code/Chap06/ObsAttrib/ObsAttrib/Class1.cs(20): 'ObsAttrib.SomeClass.OldFunc()' 已過時: 'Don't use OldFunc, use NewFunc instead'
 
5. DllImport和StructLayout屬性

DllImport可以讓C#代碼調用本機代碼中的函數,C#代碼通過平臺調用(platform invoke)這個運行時功能調用它們。

如果你希望運行時環境將結構從托管代碼正確地編組現非托管代碼(或相反),那么需要為結構的聲明附加屬性。為了使結構參數可以被正確的編組,必須使用StructLayout屬性聲明它們,指出數據應該嚴格地按照聲明中列出的樣子進行布局。如果不這么做,數據將不能正確地被編組,而應用程序可能會出錯。

using System;using System.Runtime.InteropServices; // for DllImportnamespace nativeDLL{  public class Test  {//  [DllImport ("user32.dll")] // all the defaults are OK   [DllImport("user32", EntryPoint="MessageBoxA",    SetLastError=true,    CharSet=CharSet.Ansi, ExactSpelling=true,    CallingConvention=CallingConvention.StdCall)]   public static extern int MessageBoxA (    int h, string m, string c, int type);   [StructLayout(LayoutKind.Sequential)]   public class SystemTime {    public ushort wYear;    public ushort wMonth;    public ushort wDayOfWeek;    public ushort wDay;    public ushort wHour;    public ushort wMinute;    public ushort wSecond;    public ushort wMilliseconds;   }   [DllImport ("kernel32.dll")]   public static extern void GetLocalTime(SystemTime st);   [STAThread]   public static void Main(string[] args)   {    MessageBoxA(0, "Hello World", "nativeDLL", 0);    SystemTime st = new SystemTime();    GetLocalTime(st);    string s = String.Format("date: {0}-{1}-{2}",     st.wMonth, st.wDay, st.wYear);    string t = String.Format("time: {0}:{1}:{2}",     st.wHour, st.wMinute, st.wSecond);    string u = s + ", " + t;    MessageBoxA(0, u, "Now", 0);   }  }}

6. 配件屬性

當使用.NET產生任何類型的C#工程時,會自動的產生一個AssemblyInfo.cs源代碼文件以及應用程序源代碼文件。AssemblyInfo.cs中含有配件中代碼的信息。其中的一些信息純粹是信息,而其它信息使運行時環境可以確保惟一的命名和版本號,以供重用你的配件的客戶代碼使用。
 
7. 上下文屬性

.NET柜架還提供了另一種屬性:上下文屬性。上下文屬性提供了一種截取機制,可以在類的實例化和方法調用之前和之后進行處理。這種功能用于對象遠程調用,它是從基于COM的系統所用的COM+組件服務和Microsoft Transaction Services(MTS)。

希望本文所述對大家的C#程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久国产一区二区三区| 97在线视频国产| 国产精品尤物福利片在线观看| 欧美性感美女h网站在线观看免费| 亚洲春色另类小说| xxxx欧美18另类的高清| 欧美亚洲一区在线| 亚洲色图激情小说| 久久久久久国产精品久久| 日韩欧美中文免费| 日韩电影中文字幕av| 国产亚洲xxx| 国产一区玩具在线观看| 欧美激情va永久在线播放| 欧美剧在线观看| 日韩精品中文字幕在线播放| 欧美性猛交xxxx黑人猛交| 国产高清在线不卡| 一区二区三区视频免费| 久久久国产精彩视频美女艺术照福利| 欧美日韩中文字幕在线| 精品国产乱码久久久久久婷婷| 91国内免费在线视频| 伊是香蕉大人久久| 国产一区欧美二区三区| 亚洲精品午夜精品| 欧美激情伊人电影| 亚洲美女免费精品视频在线观看| 亚洲日韩第一页| 日本在线观看天堂男亚洲| 精品久久久久久久久久久久久久| 欧美大肥婆大肥bbbbb| 国产精品aaaa| 久久久久久欧美| 国内成人精品视频| 国产精品99久久久久久久久| 精品久久久视频| 日韩欧美成人免费视频| 国产亚洲精品久久久优势| 国产精品对白刺激| 国产mv免费观看入口亚洲| 日韩美女免费线视频| 伊人久久免费视频| 国产一区二区三区在线| 国产精品专区第二| 国产精品久久久久久久久久小说| 国产精品久久久久久久久免费看| 国产精品中文字幕在线| 91久久国产综合久久91精品网站| 亚洲一级片在线看| 欧美性猛交xxx| 亚洲人午夜色婷婷| 成人欧美一区二区三区黑人孕妇| 国产91精品久久久久久| 国产精品1234| 亚洲视频电影图片偷拍一区| 亚洲亚裔videos黑人hd| 国产精品夜间视频香蕉| 91网站在线看| 97超视频免费观看| 中文字幕一精品亚洲无线一区| 深夜福利91大全| 久热爱精品视频线路一| 97在线精品国自产拍中文| 国产精品久久久久久av| 日韩电影中文 亚洲精品乱码| 欧美激情a∨在线视频播放| 狠狠躁夜夜躁人人躁婷婷91| 91免费精品视频| 日韩精品在线视频观看| 国产福利视频一区二区| 在线观看欧美日韩| 美女久久久久久久久久久| 亚洲人精品午夜在线观看| 91在线观看免费高清| 国产高清在线不卡| 最近2019年中文视频免费在线观看| 久久精品国产96久久久香蕉| 国产成人一区二区在线| 亚洲影视九九影院在线观看| 国产日韩一区在线| 欧美亚洲一区在线| 国产午夜精品麻豆| 538国产精品视频一区二区| 成人免费视频97| 亚洲天堂av女优| www.久久久久| 日韩中文娱乐网| 欧美日韩午夜剧场| 久久中国妇女中文字幕| 久久久久久亚洲精品不卡| 欧美在线免费视频| 国产欧美精品xxxx另类| 国产日产欧美精品| 成人性生交大片免费看小说| 国产91免费看片| 国产精品久久久久久av福利| 亚洲sss综合天堂久久| 亚洲男人天堂网站| 国产精品自产拍高潮在线观看| 国产噜噜噜噜噜久久久久久久久| 狠狠做深爱婷婷久久综合一区| 精品欧美国产一区二区三区| 久久久久久有精品国产| 在线视频欧美性高潮| 国产精品久久久久999| 国产成人久久久精品一区| 久久伊人精品视频| 久久久精品免费| 91精品久久久久| 91精品啪aⅴ在线观看国产| 日韩欧美亚洲国产一区| 欧美日韩国产成人高清视频| 精品久久久久久久中文字幕| 91po在线观看91精品国产性色| 亚洲国产成人精品久久| 欧美亚洲在线观看| 亚洲精品日韩在线| 亚洲精品一区二三区不卡| 国产69精品久久久久99| 麻豆国产精品va在线观看不卡| 97免费在线视频| 亚洲毛片在线观看.| 高清一区二区三区四区五区| 欧美在线亚洲在线| 国产精品69精品一区二区三区| 91亚洲一区精品| 亚洲毛片在线看| 亚洲毛片在线看| 亚洲影视九九影院在线观看| 日韩av中文字幕在线免费观看| 国产精品视频26uuu| 综合国产在线视频| 久久精品免费播放| 欧美高清电影在线看| 日韩精品在线电影| 亚洲国产成人久久综合| 亚洲成avwww人| 亚洲aⅴ日韩av电影在线观看| 国产精品亚洲网站| 国产精品国产三级国产aⅴ9色| 亚洲色图欧美制服丝袜另类第一页| 亚洲精品国产精品国自产在线| 国产精品丝袜一区二区三区| 国产精品最新在线观看| 国产精品18久久久久久麻辣| 这里精品视频免费| 国产成人一区二区| 精品毛片网大全| 亚洲www视频| 欧美猛交免费看| 亚洲国产精品中文| 久久久免费精品| 国产精品9999| 欧美香蕉大胸在线视频观看| 亚洲综合日韩中文字幕v在线| 国产精品免费一区| 精品国产一区av| 欧美午夜电影在线| 亚洲成人网在线| 538国产精品视频一区二区| 98精品国产自产在线观看| 另类少妇人与禽zozz0性伦| 国产亚洲美女精品久久久|