概念
特性是一種允許我們向程式的程式集添加元資料的語言結構,它是用于保存程式結構資訊的某種特殊型別的類,
可以通過使用特性向程式添加宣告性資訊,一個宣告性標簽是通過放置在它所應用的元素前面的方括號([ ])來描述的,
MSDN解釋為:特性提供功能強大的方法,用以將元資料或宣告資訊與代碼(程式集、型別、方法、屬性等)相關聯,特性與程式物體關聯后,即可在運行時使用名為“反射”的技術查詢特性,
特性(Attribute)用于添加元資料,如編譯器指令和注釋、描述、方法、類等其他資訊,.Net 框架提供了兩種型別的特性:預定義特性和自定義特性,
特性具有以下屬性:
- 特性可向程式中添加元資料,元資料是有關在程式中定義的型別的資訊,所有的 .NET 程式集都包含指定的一組元資料,這些元資料描述在程式集中定義的型別和型別成員,可以添加自定義特性,以指定所需的任何附加資訊,
- 可以將一個或多個特性應用到整個程式集、模塊或較小的程式元素(如類和屬性),
- 特性可以與方法和屬性相同的方式接受引數,
- 程式可以使用反射檢查自己的元資料或其他程式內的元資料,
使用特性
特性的目的是告訴編譯器把程式結構的某組元資料嵌入程式集,它可以放置在幾乎所有的宣告中(但特定的屬性可能限制在其上有效的宣告型別),
在 C# 中,特性的指定方法為:將括在方括號中的特性名置于其應用到的物體的宣告上方,
例如:
[System.Serializable]
public class SampleClass
{
// 運行陳述句
}
一個宣告中可以放置多個特性,有兩種寫法,第一種是將獨立的特性片段互相疊在一起,第二種是使用一個特性片段,特性之間使用逗號分割,
[System.Serializable]
[MyAttribute("par1","par2")] // 獨立的特性片段
public class SampleClass
{
// 運行陳述句
}
[MyAttribute("par1","par2"), System.Serializable] // 逗號分割使用
public class SampleClass
{
// 運行陳述句
}
對于某些特性可以對給定物體進行指定多次,例如 ConditionalAttribute :
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// 運行陳述句
}
特性目標
特性的目標是應用該特性的物體,例如,特性可以應用于類、特定方法或整個程式集,默認情況下,特性應用于它后面的元素,但是,您也可以顯式標識要將特性應用于方法還是它的引數或回傳值,
語法:
[target : attribute-list]

預定義特性
.Net 框架提供了三種預定義特性:AttributeUsage、Conditional、Obsolete,
AttributeUsage
AttributeUsage 描述了如何使用一個自定義特性類,它規定了特性可應用到的專案的型別,
語法:
[AttributeUsage( validon, AllowMultiple=allowmultiple, Inherited=inherited )]
引數說明:
- validon: 規定特性可被放置的語言元素,它是列舉器 AttributeTargets 的值的組合,默認值是 AttributeTargets.All,
- allowmultiple:可選的引數,為該特性的 AllowMultiple 屬性(property)提供一個布林值,如果為 true,則該特性是多用的,默認值是 false(單用的),
- inherited:可選的引數,為該特性的 Inherited 屬性(property)提供一個布林值,如果為 true,則該特性可被派生類繼承,默認值是 false(不被繼承),
示例:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
這個預定義特性標記了一個條件方法,其執行依賴于它頂的預處理識別符號,
它會引起方法呼叫的條件編譯,取決于指定的值,比如 Debug 或 Trace,例如,當除錯代碼時顯示變數的值,
語法:
[Conditional( conditionalSymbol )]
示例:
using System;
using System.Diagnostics;
namespace C_Pro
{
public class Myclass
{
[Conditional("DEBUG")]
public static void Msg(string msg)
{
Console.WriteLine(msg);
}
}
public class Test
{
static void Main()
{
Myclass.Msg("debug in Main.");
Console.WriteLine("Done.");
Console.ReadKey();
}
}
}
以debug模式進行運行:
debug in Main. Done.
Obsolete
這個預定義特性標記了不應被使用的程式物體,它可以讓您通知編譯器丟棄某個特定的目標元素,
語法:
[Obsolete( message, iserror )]
引數說明:
- message:是一個字串,描述專案為什么過時的原因以及該替代使用什么,
- iserror:是一個布林值,如果該值為 true,編譯器應把該專案的使用當作一個錯誤,默認值是 false(編譯器生成一個警告),
示例:
using System;
namespace C_Pro
{
public class MyClass
{
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod()
{
Console.WriteLine("It is the old method");
}
[Obsolete("Don't use OldMethod, use NewMethod instead", false)]
static void NewMethod()
{
Console.WriteLine("It is the new method");
}
public static void Main()
{
OldMethod();
NewMethod();
Console.ReadKey();
}
}
}
運行后結果:
Main.cs(20,4): error CS0619: `C_Pro.MyClass.OldMethod()' is obsolete: `Don't use OldMethod, use NewMethod instead' Main.cs(21,4): warning CS0618: `C_Pro.MyClass.NewMethod()' is obsolete: `Don't use OldMethod, use NewMethod instead' Compilation failed: 1 error(s), 1 warnings
如果在 VS 中可以直接看到 OldMethod() 會報錯提示:

自定義特性
宣告特性和宣告其他類是一樣的,只是所有的特性都派生自System.Attribute,
根據約定,所有特性名稱都以單詞“Attribute”結束,以便將它們與“.NET Framework”中的其他項區分,但是,在代碼中使用特性時,不需要指定 attribute 后綴,
例如定義一個MyAttributeAttribute,由 System.Attribute 派生而來,因此是自定義特性類,
public class MyAttributeAttribute : System.Attribute
{
public string product;
public string Description;
public MyAttributeAttribute(string product)
{
this.product = product;
Description = "";
}
}
特性也有建構式,和其他類一樣,每個特性至少有一個公共建構式,如果沒有宣告建構式,編譯器則會產生一個隱式、公共且無參的建構式,
建構式的引數是自定義特性的定位引數,例如上面的示例中 product 是定位引數,Description 是命名引數,任何公共的讀寫欄位或屬性都是命名引數,
定義完成后使用特性:
[Author("P. Pro", Description = "Description")]
class SampleClass
{
// 執行陳述句
}
特性與注釋的區別
注釋是對程式源代碼的一種說明,主要目的是給人看的,在程式被編譯的時候會被編譯器所丟棄,因此,它絲毫不會影響到程式的執行,
Attribute是程式代碼的一部分,它不但不會被編譯器丟棄,而且還會被編譯器編譯行程式集(Assembly)的元資料(Metadata)里,在程式運行的時候,隨時可以從元資料(元資料:.NET中元資料是指程式集中的命名空間、類、方法、屬性等資訊,這些資訊是可以通過Reflection讀取出來的,)中提取提取出這些附加資訊,并以之決策程式的運行,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/36.html
標籤:C#
