<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 值. 构造器不能被继承 ...
随机推荐
- 卸载vs2017
卸载enterprise版本 Microsoft.FSharp.SDK.Core卸载失败Package 'Microsoft.FSharp.SDK.Core,version=15.7.20180605 ...
- BZOJ 2648 kd-tree模板
学习了一下kd-tree的基本写法 http://blog.csdn.net/jiangshibiao/article/details/34144829 配合 http://www.bilibili. ...
- UVa 11400 照明系统设计
https://vjudge.net/problem/UVA-11400 题意: 有一个照明系统需要用到n种灯,每种灯的电压为V,电源费用K,每个灯泡费用为C,需要该灯的数量为L.注意到,电压相同的灯 ...
- #使用ListView更新数据出现闪烁解决办法
//使用双缓冲:添加新类继承ListView 对其重写 public class DoubleBufferListView : ListView { public DoubleBufferListVi ...
- CRLF line terminators导致shell脚本报错:command not found --转载
Linux和Windows文本文件的行结束标志不同.在Linux中,文本文件用"/n"表示回车换行,而Windows用"/r/n"表示回车换行.有时候在Wind ...
- ssh 连接不同无线网且IP以及用户名都相同
问题现场及解析 用OpenSSH的人都知ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts. 当下次访问相同计算机时,OpenSSH会核对公钥. ...
- MS SQL动态创建临时表
开发业务需求,需要对一个表作数据分析,由于数据量较大,而且分析时字段会随条件相应变化而变化. 因此计划先把数据转插入一个临时表,再对临时表的数据进行分析. 问题点是如何动态创建临时表.原先Insus. ...
- URAL 1029 Ministry
URAL 1029 思路: dp+记录路径 状态:dp[i][j]表示到(i,j)这个位置为止的最少花费 初始状态:dp[1][i]=a[1][i](1<=i<=m) 状态转移:dp[i] ...
- export与export default exports与module.exports的用法
转载:http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632 本文原创地址链接:http://blog.csdn.net/zhou_ ...
- Java 写数据到文件
private boolean writeToFile(BusGpsBean gpsBean) { String dataStr = DateUtil.date2String(new Date(), ...