C#中的⽅括号[](特性、属性)
约定:
1.”attribute” 和 ”attributes” 均不翻译
2.”property” 译为“属性”
3.msdn 中的原句不翻译话费可以干嘛
4.”program entity” 译为 ” 语⾔元素 ”
Attributes in C#
介绍
Attributes 是⼀种新的描述信息,我们既可以使⽤ attributes 来定义设计期信息(例如帮助⽂件,⽂档的 URL ),还可以⽤ attributes 定义运⾏时信息(例如,使 XML 中的元素与类的成员字段关联起来)。我们也可以⽤ attributes 来创建⼀个“⾃描述”的组件。在这篇指南中我们将明⽩怎么创建属性并将其绑定⾄各种语⾔元素上,另外我们怎样在运⾏时环境下获取到 attributes 的⼀些信息。样歌词
定义
MSDN 中做如下定义 (ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsh spec_17_2.htm)
"An attribute is a piece of additional declarative information that is specified for a declaration."
使⽤预定义 Attributes
在 c# 中已有⼀⼩组预定义的 attributes ,在我们学习怎样创建⾃定义 attributes 前,先来了解下在我们的代码中使⽤那些预定义的 attributes.
1using System;
2
3public class AnyClass
4
5 {
6 [Obsolete( " Don't u Old method, u New method " , true )]
7
8static void Old( ) { }
9
10static void New( ) { }
11
12public static void Main( )
13 {
14 Old( );
15 }
16 }
仔细看下该实例,在该实例中我们⽤到了 ”Obsolete”attribute ,它标记了⼀个不该再被使⽤的语⾔元素(译者注:这⾥的元素为⽅法),该属性的第⼀个参数是 string 类型,它解释为什么该元素被荒弃,以及我们该使⽤什么元素来代替它。实际中,我们可以书写任何其它⽂本来代替这段⽂本。第⼆个参数是告诉编译器把依然使⽤这被标识的元素视为⼀种错误,这就意味着编译器会因此⽽产⽣⼀个警告。
当我们试图编译上⾯的上⾯的程序,我们会得到如下错误:
AnyClass.Old()' is obsolete: 'Don't u Old method, u New method'
开发⾃定义 Attributes
现在我们即将了解怎么开发⾃定义的 attributes 。这⼉有个⼩⼩处⽅,有它我们就可以学会创建⾃定义的 attributes 。
在 C# 中,我们的 attribute 类都派⽣于 System.Attribute 类 ( A class that derives from the abstract class System.Attribute, whether directly or indirectly, is an attribute class. The declaration of an attribute class defines a new kind of attribute that can be placed on a declaration ),我们就这么⾏动吧。
using System;
public class HelpAttribute : Attribute
{
}
不管你是否相信我,就这样我们就已经创建了⼀个⾃定义 attribute 。现在就可以⽤它来装饰我们的类了,就像我们使⽤ obsolete attribute ⼀样。
[Help()]
public class AnyClass
}
注意:按惯例我们是⽤ ”Attribute“ 作为 attribute 类名的后缀,然⽽,当我们当我们把 attribute 绑定到某语⾔元素时,是不包含 “Attribute“ 后缀的。编译器⾸先在 System.Attribute 的继承类中查找该 attribute ,如果没有找到,编译器会把 “Attribute“ 追加到该 attribute 的名字后⾯,然后查找它。
但是迄今为⽌,该 attribute 没有任何⽤处。为了使它有点⽤处,让我们在它⾥⾯加点东西吧。
using System;
public class HelpAttribute : Attribute
{
public HelpAttribute(String Descrition_in)
{
this .description = Description_in;
}
生日贺卡怎么写
protected String description;
public String Description
{
get
{
return this .description;
}
}
}
[Help( " this is a do-nothing class " )]
public class AnyClass
{
}
在上⾯的例⼦中,我们在 attribute 类中添加了⼀个属性,在最后⼀节中,我们将在运⾏时查询该属性。
酸菜炒
定义或控制⾃定义 Attribute 的⽤法
AttributeUsage 类是另⼀预定义类(译者注: attribute 类本⾝⽤这个 atrribute System.AttributeUsage 来标记),它将帮助我们控制我们⾃定义 attribute 的⽤法,这就是,我们能为⾃定义的 attribute 类定义 attributes 。
它描述了⼀个⾃定义 attribute 类能被怎样使⽤。
AttributeUsage 提供三个属性,我们能将它们放置到我们的⾃定义 attribute 类上,第⼀个特性是:
ValidOn
通过这个属性,我们能指定我们的⾃定义 attribute 可以放置在哪些语⾔元素之上。这组我们能把⾃定义 attribute 类放置其上的语⾔元素被放在枚举器 AttributeTargets 中。我们可以使⽤ bitwi(译者注:这个词不知道怎么翻译好,但他的意思是可以这么⽤: [AttributeUsage ( ( AttributeTargets)4 , AllowMultiple = fal , Inherited = fal )], 4 代表就是 “ class ” 元素,其它诸如 1 代表“ asmbly ”, 16383 代表“ all ”等等)或者 ”.” 操做符绑定⼏个 AttributeTargets 值。(译者注:默认值为 AttributeTargets.All )
AllowMultiple
该属性标识我们的⾃定义 attribte 能在同⼀语⾔元素上使⽤多次。(译者注:该属性为 bool 类型,默认值为 fal ,意思就是该⾃定义attribute 在同⼀语⾔元素上只能使⽤⼀次)
Inherited
我们可以使⽤该属性来控制我们的⾃定义 attribute 类的继承规则。该属性标识我们的⾃定义 attribute 是否可以由派⽣类继承。((译者注:该属性为 bool 类型,默认值为 fal ,意思是不能继承)
让我们来做点实际的东西吧,我们将把 AttributeUsage attribute 放置在我们的 help attribute 上并在它的帮助下,我们来控制 help attribute 的⽤法。
using System;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = fal , Inherited = fal )]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this .description = Description_in;
protected String description;
public String Description
{
get
{
return this .description;
}
}
}
⾸先我们注意 AttributeTargets.Class . 它规定这个 help attribute 只能放置在语⾔元素 ”class” 之上。这就意味着,下⾯的代码将会产⽣⼀个错误。
AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.
现在试着把它绑定到⽅法。
[Help( " this is a do-nothing class " )]
public class AnyClass
{
[Help( " this is a do-nothing method " )] // error
public void AnyMethod()
{
}
}
我们可以使⽤ AttributeTargets.All 来允许 Help attribute 可以放置在任何预定义的语⾔元素上,那些可能的语⾔元素如下 :
intel处理器Asmbly,
Module,
野古草Class,
Struct,
Enum,
Constructor,
Method,
Property,
Field,
nt,
Interface,
Parameter,
Delegate,
All = Asmbly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | nt | Interface | Parameter | Delegate, ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | nt | Delegate | Interface )
~ 现在考虑下 AllowMultiple = fal . 这就规定该 attribute 不能在同⼀语⾔元素上放置多次 .
[Help( " this is a do-nothing class " )]
[Help( " it contains a do-nothing method " )]
public class AnyClass
{
[Help( " this is a do-nothing method " )] // error
public void AnyMethod()
{
}
}
它产⽣了⼀个编译错误:
AnyClass.cs: Duplicate 'Help' attribute
Ok !现在我们该讨论下最后那个属性了, ”Inherited”, 指出当把该 attribute 放置于⼀个基类之上,是否派⽣类也继承了该 attribute 。如果绑定⾄某个 attribute 类的 ”Inherited” 被设为 true, 那么该 attribute 就会被继承,然⽽如果绑定⾄某个 attribute 类的 ”Inherited” 被设为 fal 或者没有定义,那么该 attribute 就不会被继承。
让我们假设有如下的类关系。
什么欲试成语
[Help( " BaClass " )]
public class Ba
{
}
public class Derive : Ba
{
}
我们有四种可能的绑定 :
[AttributeUsage(AttributeTargets.Class, AllowMultiple = fal , Inherited = fal )]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true , Inherited = fal) ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = fal , Inherited = true )]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true , Inherited = true) ]
第⼀种情况
如果我们查询(我们将在后⾯来了解如何在运⾏时来查询 attributes )派⽣类中的 help attribute ,我们将不可能查询到因为”Inherited” 被设为了 fal 。
第⼆种情况
第⼆种情况没有什么不同,因为其 ”Inherited” 也被设为了 fal 。
第三种情况
为了解释第三种和第四种情况,让我们为派⽣类也绑定同⼀ attribute 。
[Help( " BaClass " )]
public class Ba
{
}
[Help( " DeriveClass " )]
public class Derive : Ba
{
}
现在我们查询相关的 help attribute ,我们将仅仅可以得到派⽣类的 attribute ,为什么这样是因为 help attribute 虽然允许被继承,但不能多次在同⼀语⾔元素上使⽤,所以基类中的 help attribute 被派⽣类的 help attribute 重写了。
第四种情况
在第四种情况中,当我们查询派⽣类的 help attribute 时,我们可以得到两个 attributes ,当然是因为 help attribute 既允许被继承,⼜允许在同⼀语⾔元素上多次使⽤的结果。
注意: AttributeUsage attribute 仅应⽤在那种是 System.Attribute 派⽣的 attriubte 类⽽且绑定值该 attriubte 类的 AllowMultiple 和 Inherited 均为 fal 上才是有效的。
可选参数 vs. 命名参数
可选参数是 attribute 类构造函数的参数。它们是强制的,必须在每次在 attribute 绑定⾄某语⾔元素时提供⼀个值。⽽另⼀⽅⾯,命名参数倒是真正的可选参数,不是在 attribute 构造函数的参数。
为了更加详细的解释,让我们在 Help 类中添加另外的属性。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = fal ,
Inherited = fal )]
幻想与现实public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this .description = Description_in;
this .verion = " No Version is defined for this class " ;
}
protected String description;
public String Description
{
get
{
return this .description;
}
}
protected String version;
public String Version
{
get
{
return this .version;
}
// if we EVE r want our attribute ur to t this property,
// we must specify t method for it
t
{
this .verion = value;
}
}
}
[Help( " This is Class1 " )]
public class Class1
{
}
[Help( " This is Class2 " , Version = " 1.0 " )]
public class Class2