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" 是构造器的参数,称为定位参数,必须指定.
  • CharSetSetLastError 用于设置字段或属性,称为命名参数,是可选的.
  • 在C#中,既可将每个特性都封闭到一对方括号中,也可在一对方括号中封闭多个以逗号分隔的特性.如果特性类的构造器不获取参数,那么圆括号也可以省略,如:
    • [Serializable][Flags]
    • [Serializable,Flags]
    • [FlagsAttribute,SerializableAttribute]
    • [FlagsAttribute(), SerializableAttribute()]

18.2 定义自己的特性类

    1. 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,GetCustomAttributesGetCustomAttribute
  • IsDefined 比另外两个方法更高效,因为 IsDefined 不会构造特性对象,不会调用构造器,也不会设置字段和属性.

18.5 两个特性实例的相互匹配

  • System.Attribute 重写了 ObjectEquals 方法,利用反射来比较两个特性对象中的字段值(为每个字段都调用 Equals).所有字段都匹配就返回 true ; 否则返回 false.建议重写 Equals 来移除反射的使用.
  • System.Attribute 还公开了虚方法 Match ,其默认实现只是调用 Equals 方法并返回它的结果.

18.6 检测定制特性时不创建从Attribute派生的对象

18.7 条件特性类

<NET CLR via c# 第4版>笔记 第18章 定制特性的更多相关文章

  1. <NET CLR via c# 第4版>笔记 第19章 可空值类型

    System.Nullable<T> 是结构. 19.1 C# 对可空值类型的支持 C# 允许用问号表示法来声明可空值类型,如: Int32? x = 5; Int32? y = null ...

  2. <NET CLR via c# 第4版>笔记 第17章 委托

    17.1 初识委托 .net 通过委托来提供回调函数机制. 委托确保回调方法是类型安全的. 委托允许顺序调用多个方法. 17.2 用委托回调静态方法 将方法绑定到委托时,C# 和 CLR 都允许引用类 ...

  3. <NET CLR via c# 第4版>笔记 第16章 数组

    //创建一个一维数组 int[] myIntegers; //声明一个数组引用 myIntegers = new int[100]; //创建含有100个int的数组 //创建一个二维数组 doubl ...

  4. <NET CLR via c# 第4版>笔记 第13章 接口

    13.1 类和接口继承 13.2 定义接口 C#用 interface 关键字定义接口.接口中可定义方法,事件,无参属性和有参属性(C#的索引器),但不能定义任何构造器方法,也不能定义任何实例字段. ...

  5. <NET CLR via c# 第4版>笔记 第12章 泛型

    泛型优势: 源代码保护 使用泛型算法的开发人员不需要访问算法的源代码.(使用c++模板的泛型技术,算法的源代码必须提供给使用算法的用户) 类型安全 向List<DateTime>实例添加一 ...

  6. <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型

    5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...

  7. <NET CLR via c# 第4版>笔记 第6章 类型和成员基础

    6.1 类型的各种成员 6.2 类型的可见性 public 全部可见 internal 程序集内可见(如忽略,默认为internal) 可通过设定友元程序集,允许其它程序集访问该程序集中的所有inte ...

  8. <NET CLR via c# 第4版>笔记 第7章 常量和字段

    7.1 常量 常量 是值从不变化的符号.定义常量符号时,它的值必须能够在编译时确定. 只能定义编译器识别的基元类型的常量,如果是非基元类型,需把值设为null. 常量的值直接嵌入代码,所以不能获取常量 ...

  9. <NET CLR via c# 第4版>笔记 第8章 方法

    8.1 实例构造器和类(引用类型) 构造引用类型的对象时,在调用类型的实例构造器之前,为对象分配的内存总是先被归零 .没有被构造器显式重写的所有字段都保证获得 0 或 null 值. 构造器不能被继承 ...

随机推荐

  1. 【第三十八章】 springboot+docker(maven)

    回顾上一章的整个部署过程: 使用"mvn install"进行打包jar 将jar移动到与Dockerfile文件相同的文件夹下 编写Dockerfile文件 使用"do ...

  2. 配置文件(Machine.config、Web.config、App.config)

    Machine.config1.该文件在Windows目录下\Microsoft.net\framework\[version]\Config\2.为了提高性能,该文件只包含不同于默认值的设置.并且定 ...

  3. 小米笔记本 air 12.5寸 支持硬盘参数

    M.2接口 2280规格 单面芯片固态硬盘 PCIE协议

  4. 《WAP》团队第三次作业--团队项目的原型设计与开发

    一· 目 录 第一部分 · 结 对 成 员 明 细 第二部分 · NABCD 模 型 第三部分 · 原 型 设 计 第四部分 · P S P  第五部分 · 结 对 过 程 第六部分 · 心 得 总 ...

  5. eclipse开发go语言入门案例

    1.配置eclipse下配置GO语言的插件 点击eclipse的“Help”菜单,找到“Install New Software…”菜单项.如下图: 点击“Install New Software…” ...

  6. Flutter实战:手把手教你写Flutter Plugin

    前言 如果你对移动端有所关注,那么你一定会听说过Flutter.得益于Google,Flutter一经推出便得受到了广泛关注.很多开发者跃跃欲试,国内部分大厂,诸如美团.闲鱼等团队已经开始了Flutt ...

  7. URAL 1501 Sense of Beauty

    URAL 1501 思路: dp+记忆化搜索 状态:dp[i][j]表示选取第一堆前i个和第二堆前j的状态:0:0多1个              1:0和1相等                2:1 ...

  8. [.NET开发] C#面向服务WebService从入门到精通

    C#面向服务WebService从入门到精通>包含以下两个部分: 一.<C#远程调用技术WebService修炼手册[基础篇]> 本次分享课您将学习到以下干货知识点: 1).WebS ...

  9. Jaccard similarity(杰卡德相似度)和Abundance correlation(丰度相关性)

    杰卡德距离(Jaccard Distance) 是用来衡量两个集合差异性的一种指标,它是杰卡德相似系数的补集,被定义为1减去Jaccard相似系数.而杰卡德相似系数(Jaccard similarit ...

  10. English trip -- VC(情景课)1 E Writing

    Talk with a partner ['pɑːtnə] (伙伴)  与同伴说一说 Comple the words 写全单词 first second third last name area c ...