读书笔记_C#技术内幕_第二十七章(属性)
2008-09-07 12:36
246 查看
属性(attribute)是程序的元素,它们装饰代码以便为程序提供声明的功能和元数据(metadata)。元数据是关于程序、它的内部元素和开发人员可能感兴趣的代码等方面的信息。其它语言和系统使用接口定义语言(Interface Definition Language,IDL)、接口、类库和基本反射获得程序的元数据。
C#使用反射来获得元数据,而且使用属性来表达附加的元数据。反射是发现程序在运行时刻的信息的一种方法。属性为开发人员提供了一种手段以便为逻辑、反射和工具支持显式的将装饰包括在它们的代码中。
属性容易使用并且有它们自己的独特的语法。大多数程序都使用预定义的系统属性,许多属性都在系统库中。当预定义的库不够用时,可以创建自定义的属性。
使用属性:
属性放置在所引用的程序元素的上一行中,并且被方括号包围。在方括号内有一个或多个以逗号分隔的属性。属性的参数可以作为位置参数或命名参数来指定。
[attributename1, attributename2]
如:[Flags]给予枚举像位字段(bitfield)一样的能力,[Flags, Serializable]还意味着元素可以串行化。
使用属性参数:
属性参数能够用指定到已编写的代码中的信息初始化属性。由于属性是另外一种对象,所以该参数与实例构造函数中的参数的作用相同。主要的差别是它可以同时初始化共同的属性字段和参数。
有两种类型的参数:位置参数(positional parameter)和命名参数(named parameter)。参数只能够包括位置参数,或只包括命名参数,或者位置参数和命名参数的组合。位置属性是强制性的并且始终在命名属性之前。
位置参数:
位置参数与属性的公共构造函数是对应的。如果只有一个公共构造函数,就必须使用那个构造函数的参数。否则可以使用属性的任何可用的公共构造函数的位置参数。位置参数必须为所实现的属性构造函数整体指定并且按适当顺序来指定。
class PositionalParameter
{
[Obsolete("Use this method at your own risk!")]
public static void OldMethod()
{
}
static void Main(string[] args)
{
OldMethod();
}
}
上面的程序中Obsolete属性使用了一个位置参数。该参数是用来在编译期间显式消息的字符串。按默认设置,这个显示的内容是警告,但是Obsolete属性有另外一个叫做IsError的位置参数。如果写成
[Obsolete("Use this method at your own risk!", true)]
IsError位置参数生成了一个编译时的错误,其中显示了来自第一个位置参数的消息。
命名参数:
命名参数与公共读写字段和属性的特性是对应了。它是一个编译错误,因为命名参数用于静态的或只读的字段或属性。
[StructLayout( LayoutKind.Auto, CharSet=CharSet.Unicode)]
class NamedParameter
{
static void Main(string[] args)
{
}
}
上面的程序展示了怎样使用命名参数。StructLayout属性有它的位置参数,然后是命名参数。其中位置参数是必须的。命名参数有一个名称标签、等号,然后是参数值。StructLayout属性用于传递类和结构到非管理的代码,代码中的成员的物理布局必须精确。
使用属性目标:
属性目标(attribute target)指定了属性被应用到什么程序元素。它们不是始终必需的,但是有时能够帮助清楚的了解属性的意图。例如,如果对于属性是应用到方法的返回值或方法的本身弄不清楚,那么属性的目标规范就会解决这种模糊。
[assembly:CLSCompliant(false)]
class AttributeTarget
{
static void Main(string[] args)
{
}
}
上面的程序中,属性指定了CLSCompliant属性应用到assembly而不是它附近的类。它有用冒号与CLSCompliant属性分开的目标——assembly。
假如没有指定目标,就没有办法断定这个属性所装饰的是类或者是assembly。假如位置参数是真,则在应用CLSComplaint属性到其它程序元素之前,先要求有assembly目标。
目标名称 应用于
all 任何元素
assembly 整个配件
class 类
constructor 构造函数
delegate 委托
enum 枚举
event 事件
field 字段
interface 接口
method 方法
module 包含的模块
param 参数
property 特性
return 返回值
struct 结构
创建自己的属性
创建自己的属性类似于创建普通的类,只是它是用AttributeUsage属性来装饰的并且从System.Attribute类继承。
AttributeUsage属性:
Attribute属性指定有多少属性能够在程序中应用。它决定什么程序元素能够使用什么属性,该属性是否能够多次使用,以及该属性是否能够继承。
可用的元素
一些属性只在某些程序元素上有意义。如下表
目标名称 说明
All 任何Attribute Target成员
Assembly 配件
Class 类
ClassMembers 类、构造函数、委托、枚举、事件、字段、接口、方法、参数、属性或结构
Constructor 构造函数
Delegate 委托
Enum 枚举
Event 事件
Field 字段
Interface 接口
Method 方法
Module 模块
Parameter 参数
Property 特性
Return Value 返回值
Struct 结构
AttributeUsage属性的使用方法与任何其它属性一样。它有如前所述的位置参数和两个命名参数。
[AttributeUsage(AttributeTargets.All,
AllowMultiple = true,
Inherited = true)]
class TrackerAttribute : Attribute
{
// Implementation
}
TrackerAttribute类的字段必须为公共字段,如果为专用字段,则必须通过类属性来显示。属性类字段和特性(property)都必须是可读写的和公共的。
C#属性的通用命名规则是添加“Attribute”后缀到属性类的命名声明中。当实际使用属性时,可以通过去掉“Attribute”后缀来使用快捷方式,并且C#仍然认识适当的属性。
多重性
属性可用于某个程序元素的次数是通过AttributeUsage属性的AllowMultiple命名参数来指定的。为true时,它可以在程序元素上多次使用,否则,只能使用一次。
继承性:
使用AttributeUsage属性的命名参数Inherited来控制属性的继承性。基本上Inherited命名参数在意义方面类似于C#的sealed修饰符。
从类中获得属性:类的属性可以通过使用Attribute类的GetCustomAttribute()和GetCustomAttributes()方法来获得。通过获取要检查的类的Type对象和要检索的属性的Type对象可以得到attribute对象。
C#使用反射来获得元数据,而且使用属性来表达附加的元数据。反射是发现程序在运行时刻的信息的一种方法。属性为开发人员提供了一种手段以便为逻辑、反射和工具支持显式的将装饰包括在它们的代码中。
属性容易使用并且有它们自己的独特的语法。大多数程序都使用预定义的系统属性,许多属性都在系统库中。当预定义的库不够用时,可以创建自定义的属性。
使用属性:
属性放置在所引用的程序元素的上一行中,并且被方括号包围。在方括号内有一个或多个以逗号分隔的属性。属性的参数可以作为位置参数或命名参数来指定。
[attributename1, attributename2]
如:[Flags]给予枚举像位字段(bitfield)一样的能力,[Flags, Serializable]还意味着元素可以串行化。
使用属性参数:
属性参数能够用指定到已编写的代码中的信息初始化属性。由于属性是另外一种对象,所以该参数与实例构造函数中的参数的作用相同。主要的差别是它可以同时初始化共同的属性字段和参数。
有两种类型的参数:位置参数(positional parameter)和命名参数(named parameter)。参数只能够包括位置参数,或只包括命名参数,或者位置参数和命名参数的组合。位置属性是强制性的并且始终在命名属性之前。
位置参数:
位置参数与属性的公共构造函数是对应的。如果只有一个公共构造函数,就必须使用那个构造函数的参数。否则可以使用属性的任何可用的公共构造函数的位置参数。位置参数必须为所实现的属性构造函数整体指定并且按适当顺序来指定。
class PositionalParameter
{
[Obsolete("Use this method at your own risk!")]
public static void OldMethod()
{
}
static void Main(string[] args)
{
OldMethod();
}
}
上面的程序中Obsolete属性使用了一个位置参数。该参数是用来在编译期间显式消息的字符串。按默认设置,这个显示的内容是警告,但是Obsolete属性有另外一个叫做IsError的位置参数。如果写成
[Obsolete("Use this method at your own risk!", true)]
IsError位置参数生成了一个编译时的错误,其中显示了来自第一个位置参数的消息。
命名参数:
命名参数与公共读写字段和属性的特性是对应了。它是一个编译错误,因为命名参数用于静态的或只读的字段或属性。
[StructLayout( LayoutKind.Auto, CharSet=CharSet.Unicode)]
class NamedParameter
{
static void Main(string[] args)
{
}
}
上面的程序展示了怎样使用命名参数。StructLayout属性有它的位置参数,然后是命名参数。其中位置参数是必须的。命名参数有一个名称标签、等号,然后是参数值。StructLayout属性用于传递类和结构到非管理的代码,代码中的成员的物理布局必须精确。
使用属性目标:
属性目标(attribute target)指定了属性被应用到什么程序元素。它们不是始终必需的,但是有时能够帮助清楚的了解属性的意图。例如,如果对于属性是应用到方法的返回值或方法的本身弄不清楚,那么属性的目标规范就会解决这种模糊。
[assembly:CLSCompliant(false)]
class AttributeTarget
{
static void Main(string[] args)
{
}
}
上面的程序中,属性指定了CLSCompliant属性应用到assembly而不是它附近的类。它有用冒号与CLSCompliant属性分开的目标——assembly。
假如没有指定目标,就没有办法断定这个属性所装饰的是类或者是assembly。假如位置参数是真,则在应用CLSComplaint属性到其它程序元素之前,先要求有assembly目标。
目标名称 应用于
all 任何元素
assembly 整个配件
class 类
constructor 构造函数
delegate 委托
enum 枚举
event 事件
field 字段
interface 接口
method 方法
module 包含的模块
param 参数
property 特性
return 返回值
struct 结构
创建自己的属性
创建自己的属性类似于创建普通的类,只是它是用AttributeUsage属性来装饰的并且从System.Attribute类继承。
AttributeUsage属性:
Attribute属性指定有多少属性能够在程序中应用。它决定什么程序元素能够使用什么属性,该属性是否能够多次使用,以及该属性是否能够继承。
可用的元素
一些属性只在某些程序元素上有意义。如下表
目标名称 说明
All 任何Attribute Target成员
Assembly 配件
Class 类
ClassMembers 类、构造函数、委托、枚举、事件、字段、接口、方法、参数、属性或结构
Constructor 构造函数
Delegate 委托
Enum 枚举
Event 事件
Field 字段
Interface 接口
Method 方法
Module 模块
Parameter 参数
Property 特性
Return Value 返回值
Struct 结构
AttributeUsage属性的使用方法与任何其它属性一样。它有如前所述的位置参数和两个命名参数。
[AttributeUsage(AttributeTargets.All,
AllowMultiple = true,
Inherited = true)]
class TrackerAttribute : Attribute
{
// Implementation
}
TrackerAttribute类的字段必须为公共字段,如果为专用字段,则必须通过类属性来显示。属性类字段和特性(property)都必须是可读写的和公共的。
C#属性的通用命名规则是添加“Attribute”后缀到属性类的命名声明中。当实际使用属性时,可以通过去掉“Attribute”后缀来使用快捷方式,并且C#仍然认识适当的属性。
多重性
属性可用于某个程序元素的次数是通过AttributeUsage属性的AllowMultiple命名参数来指定的。为true时,它可以在程序元素上多次使用,否则,只能使用一次。
继承性:
使用AttributeUsage属性的命名参数Inherited来控制属性的继承性。基本上Inherited命名参数在意义方面类似于C#的sealed修饰符。
从类中获得属性:类的属性可以通过使用Attribute类的GetCustomAttribute()和GetCustomAttributes()方法来获得。通过获取要检查的类的Type对象和要检索的属性的Type对象可以得到attribute对象。
相关文章推荐
- 读书笔记_C#技术内幕_第二章
- 读书笔记_C#技术内幕_第十二章(使用命名空间组织代码)
- 读书笔记_C#技术内幕_第十五章(执行转换)
- 读书笔记_C#技术内幕_第三十章(不安全代码和平台调用)
- 读书笔记_C#技术内幕_第十三章(创建结构)
- 读书笔记_C#技术内幕_第十七章(文件的输入/输出和串行化)
- 读书笔记_C#技术内幕_第二十九章(本地化和资源)
- 读书笔记_C#技术内幕_第三章(C#表达式)
- 读书笔记_C#技术内幕_第九章(重载类成员和操作符)
- 读书笔记_C#技术内幕_第十四章(实现接口)
- 读书笔记_C#技术内幕_第二十三章(多线程)
- 读书笔记_C#技术内幕_剩余章节
- 读书笔记_C#技术内幕_第六章(对象和组件概念)
- 读书笔记_C#技术内幕_第十章(处理异常和错误)
- 读书笔记_C#技术内幕_第二十五章(字符串操作)(String类)
- 读书笔记_C#技术内幕_第七章(类的使用)
- 读书笔记_C#技术内幕_第二十五章(字符串操作)(StringBuilder,字符串格式化)
- 读书笔记_C#技术内幕_第八章(设计面向对象的程序)
- 读书笔记_C#技术内幕_第二十六章(C#集合)
- 读书笔记_C#技术内幕_第十一章(委托和事件)(委托部分)