<NET CLR via c# 第4版>笔记 第18章 定制特性
18.1 使用定制特性
FCL 中的几个常用定制特性.
- DllImport 特性应用于方法,告诉 CLR 该方法的实现位于指定 DLL 的非托管代码中.
- Serializable 特性应用于类型,告诉序列化格式化器一个实例的字段可以序列化和反序列化.
- AssemblyVersion 特性应用于程序集,设置程序集的版本号.
- Flags特性应用于枚举类型,枚举类型就成了位标志集合.
C# 允许用一个前缀明确指定特性要应用于的目标元素.有时可省略,编译器能推断;有时则必须指定前缀.
using System;
[assembly: SomeAttr] //应用于程序集
[module: SomeAttr] //应用于模块
[type: SomeAttr] //应用于类型
internal sealed class SomeType<[typevar: SomeAttr] T> //应用于泛型类型变量
{
[field: SomeAttr] //应用于字段
public int SomeField = 0;
[return: SomeAttr] //应用于返回值
[method: SomeAttr] //应用于方法
public int SomeMethod(
[param: SomeAttr] //应用于参数
int someParam) { return someParam; }
[property: SomeAttr] //应用于属性
public string SomeProp {
[method: SomeAttr] //应用于get访问器方法
get { return null; }
}
[event: SomeAttr] //应用于事件
[field: SomeAttr] //应用于编译器生成的字段
[method: SomeAttr] //应用于编译器生成的add & remove方法
public event EventHandler SomeEvent;
}
- CLS 要求定制特性类必须直接或间接从公共抽象类 System.Attribute 派生.
- 应用特性时,c# 编译器允许省略 Attribute 后缀以减少打字量,并提升源代码的可读性.
- 特性是类的实例,语法类似于调用类的某个实例构造器.如:
[DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
- "Kernel32" 是构造器的参数,称为定位参数,必须指定.
- CharSet 和 SetLastError 用于设置字段或属性,称为命名参数,是可选的.
- 在C#中,既可将每个特性都封闭到一对方括号中,也可在一对方括号中封闭多个以逗号分隔的特性.如果特性类的构造器不获取参数,那么圆括号也可以省略,如:
- [Serializable][Flags]
- [Serializable,Flags]
- [FlagsAttribute,SerializableAttribute]
- [FlagsAttribute(), SerializableAttribute()]
18.2 定义自己的特性类
- 从 Attribute 继承; 2) 类名有 Attribute 后缀(非必须).
- AttributeUsage 特性是一个简单的类,可利用它告诉编译器定制特性的合法应用范围.所有编译器都内建了对该特性的支持.如:
[AttributeUsage(AttributeTargets.Enum, Inherited = false)]
public class FlagsAttribute : Attribute
{
public FlagsAttribute() { }
}
- AttributeUsageAttribute 类有一个公共构造器,它允许传递位标志来指明特性的合法应用范围.
- AttributeUsageAttribute 类有两个公共属性.其中 AllowMultiple 指示是否允许将该特性多次应用于同一个目标元素; Inherited 指出特性在应用于基类时,是否同时应用于派生类和重写的方法.
- 如果忘记向自己的特性类应用 AttributeUsageAttribute 特性,则特性类默认为应用于所有目标元素,向每个目标元素都只能应用一次,而且可继承.
18.3 特性构造器和字段/属性数据类型
- 定义特性类的实例构造器\字段和属性时,只允许Boolean,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,String,Type,Object 或枚举类型.
- 应用特性时必须传递一个编译时常量表达式,它与特性类定义的类型匹配.
- 定制特性: 它是类的实例,被序列化成驻留在元数据中的字节流.远行时可对元数据中的字节进行反序列化,从而构造出类的实例.
18.4 检测定制特性
- 有三个方法可以获取与目标关联的特性: IsDefined,GetCustomAttributes 和 GetCustomAttribute
- IsDefined 比另外两个方法更高效,因为 IsDefined 不会构造特性对象,不会调用构造器,也不会设置字段和属性.
18.5 两个特性实例的相互匹配
- System.Attribute 重写了 Object 的 Equals 方法,利用反射来比较两个特性对象中的字段值(为每个字段都调用 Equals).所有字段都匹配就返回 true ; 否则返回 false.建议重写 Equals 来移除反射的使用.
- System.Attribute 还公开了虚方法 Match ,其默认实现只是调用 Equals 方法并返回它的结果.
18.6 检测定制特性时不创建从Attribute派生的对象
18.7 条件特性类
<NET CLR via c# 第4版>笔记 第18章 定制特性的更多相关文章
- <NET CLR via c# 第4版>笔记 第19章 可空值类型
System.Nullable<T> 是结构. 19.1 C# 对可空值类型的支持 C# 允许用问号表示法来声明可空值类型,如: Int32? x = 5; Int32? y = null ...
- <NET CLR via c# 第4版>笔记 第17章 委托
17.1 初识委托 .net 通过委托来提供回调函数机制. 委托确保回调方法是类型安全的. 委托允许顺序调用多个方法. 17.2 用委托回调静态方法 将方法绑定到委托时,C# 和 CLR 都允许引用类 ...
- <NET CLR via c# 第4版>笔记 第16章 数组
//创建一个一维数组 int[] myIntegers; //声明一个数组引用 myIntegers = new int[100]; //创建含有100个int的数组 //创建一个二维数组 doubl ...
- <NET CLR via c# 第4版>笔记 第13章 接口
13.1 类和接口继承 13.2 定义接口 C#用 interface 关键字定义接口.接口中可定义方法,事件,无参属性和有参属性(C#的索引器),但不能定义任何构造器方法,也不能定义任何实例字段. ...
- <NET CLR via c# 第4版>笔记 第12章 泛型
泛型优势: 源代码保护 使用泛型算法的开发人员不需要访问算法的源代码.(使用c++模板的泛型技术,算法的源代码必须提供给使用算法的用户) 类型安全 向List<DateTime>实例添加一 ...
- <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型
5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...
- <NET CLR via c# 第4版>笔记 第6章 类型和成员基础
6.1 类型的各种成员 6.2 类型的可见性 public 全部可见 internal 程序集内可见(如忽略,默认为internal) 可通过设定友元程序集,允许其它程序集访问该程序集中的所有inte ...
- <NET CLR via c# 第4版>笔记 第7章 常量和字段
7.1 常量 常量 是值从不变化的符号.定义常量符号时,它的值必须能够在编译时确定. 只能定义编译器识别的基元类型的常量,如果是非基元类型,需把值设为null. 常量的值直接嵌入代码,所以不能获取常量 ...
- <NET CLR via c# 第4版>笔记 第8章 方法
8.1 实例构造器和类(引用类型) 构造引用类型的对象时,在调用类型的实例构造器之前,为对象分配的内存总是先被归零 .没有被构造器显式重写的所有字段都保证获得 0 或 null 值. 构造器不能被继承 ...
随机推荐
- Python time strptime()与time strftime()
time strftime()接收时间元组,返回表示时间的字符串. time strptime()把时间字符串,解析成一个时间元组. import time t = time.strftime('%Y ...
- Python的collections模块中的OrderedDict有序字典
如同这个数据结构的名称所说的那样,它记录了每个键值对添加的顺序. ? 1 2 3 4 5 6 d = OrderedDict() d['a'] = 1 d['b'] = 10 d['c'] = 8 f ...
- package 'orocos-bfl' not found CMake Error at /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:283 (message):
#没有数字 sudo apt-get install ros-indigo-bfl
- shell 特殊变量详解
$0 获取当前执行脚本的名称,包括路径 [root@centos test]# cat test.sh echo $0 [root@VM_102_244_centos test]# bash test ...
- 《剑指offer》第三十三题(二叉搜索树的后序遍历序列)
// 面试题33:二叉搜索树的后序遍历序列 // 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果. // 如果是则返回true,否则返回false.假设输入的数组的任意两个数字都 ...
- 《剑指offer》第九题(用两个栈实现队列)
// 面试题:用两个栈实现队列 // 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail // 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的 ...
- 《剑指offer》第三_一题(找出数组中重复的数字,可改变数组)
// 面试题3(一):找出数组中重复的数字 // 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内.数组中某些数字是重复的,但不知道有几个数字重复了, // 也不知道每个数字重复了几次.请 ...
- js、jq对象互转
1.js对象转jq对象: $() $('#kw') $(document.getElementById("kw")) 2.jq对象转js对象: $(this).get(0) ...
- Idea设置默认不折叠一行的函数
- Python requests快速上手
Python requests快速上手 这里参考官方文档,在ide中写了一遍,加深一下印象,定义的函数只是为了方便区分不同的请求方式 #-*-coding:utf-8-*- # Time:2017/1 ...