C#特性学习笔记一
元数据,就是C#中封装的一些类,无法修改.类成员的特性被称为元数据中的注释.
1、什么是特性
1)属性与特性的区别
属性(Property):属性是面向对象思想里所说的封装在类里面的数据字段,Get,Set方法。
特性(Attribute): 官方解释:特性是给指定的某一声明的一则附加的声明性信息。 允许类似关键字的描述声明。它对程序中的元素进行标注,如类型、字段、方法、属性等。从.net角度看,特性是一种 类,这些类继承于System.Attribute类,用于对类、属性、方法、事件等进行描述,主要用在反射中。但从面向对象的级别看,其实Attribute是类型级别的,而不是对象级别。
Attributes和.net文件的元素据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响程序的行为。
2、特性的应用
(1).net中特性用来处理多种问题,比如序列化、程序的安全特性、防止即时编译器对程序代码进行优化从而代码容易调试等等。
定植特性的本质上是一个类的元素上去添加附加信息,并在运行其通过反射得到该附加信息(在使用数据实体对象时经常用到)
(2)Attribute 作为编译器的指令时的应用
Conditional:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用
DllImport: 用来标记费.net的函数,表明该方法在一个外部的DLL中定义。
Obsolete: 这个属性用来标记当前的方法已经废弃,不再使用
注:Attribute是一个类,因此DllImport也是一个类,Attribute类是在编译的时候实例化,而不是像通常那样在运行时实例化。
CLSCompliant: 保证整个程序集代码遵守CLS,否则编译将报错。
3、自定义特性
使用AttributeUsage,来控制如何应用新定义的特性
[AttributeUsageAttribute(AttributeTargets.All 可以应用到任何元素
,AllowMultiple=true, 允许应用多次,我们的定值特性能否被重复放在同一个程序实体前多次。
,Inherited=false,不继承到派生
)]
特性也是一个类,必须继承于System.Attribute类,命名规范为“类名”+Attribute。不管是直接还是间接继承,都会成为一个特性类,特性类的声明定义了一种可以放置在声明之上新的特性。
public class MyselfAttribute:System.Attribute
自定义特定:
- //限定特性类的应用范围
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
- //定制MsgAttribute特性类,继承于Attribute
- public class ClassMsgAttribute : Attribute
- {
- //定义_msg字段和Msg属性//Msg属性用于读写msg字段
- string _msg;
- public string Msg { get { return _msg; } set { _msg = value; } }
- public ClassMsgAttribute() { }
- //重载构造函数接收一个参数,赋值给_msg字段
- public ClassMsgAttribute(string s) { _msg = s; }
- }
//限定特性类的应用范围
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
//定制MsgAttribute特性类,继承于Attribute
public class ClassMsgAttribute : Attribute
{
//定义_msg字段和Msg属性//Msg属性用于读写msg字段
string _msg;
public string Msg { get { return _msg; } set { _msg = value; } }
public ClassMsgAttribute() { }
//重载构造函数接收一个参数,赋值给_msg字段
public ClassMsgAttribute(string s) { _msg = s; }
}
调用:
- //在Person类上标记ClassMsg特性
- [ClassMsg(Msg = "这是关于人的姓名信息的类")]
- class Person
- {
- //在_name字段上应用ClassMsg特性
- [ClassMsg("这是存储姓名的字段")]
- string _name;
- //以下特性无法应用,因为MsgAttribute定义的特性只能用于类和字段
- //[ClassMsg("这是读写姓名字段的属性")]
- public string Name { get { return _name; } set { _name = value; } }
- }
//在Person类上标记ClassMsg特性
[ClassMsg(Msg = "这是关于人的姓名信息的类")]
class Person
{
//在_name字段上应用ClassMsg特性
[ClassMsg("这是存储姓名的字段")]
string _name;
//以下特性无法应用,因为MsgAttribute定义的特性只能用于类和字段
//[ClassMsg("这是读写姓名字段的属性")]
public string Name { get { return _name; } set { _name = value; } }
}
主函数的情况
- static void Main(string[] args)
- {
- //获取Person类的Type对象tp
- Type tp = Type.GetType("Person");
- //获取tp对象的特性数组,并将数组赋值给MyAtts
- object[] MyAtts = tp.GetCustomAttributes(false);
- //遍历并输出MyAtts数组子项的Msg属性
- foreach (ClassMsgAttribute m in MyAtts)
- {
- Console.WriteLine("Person类的特性:{0}", m.Msg);
- }
static void Main(string[] args)
{
//获取Person类的Type对象tp
Type tp = Type.GetType("Person");
//获取tp对象的特性数组,并将数组赋值给MyAtts
object[] MyAtts = tp.GetCustomAttributes(false);
//遍历并输出MyAtts数组子项的Msg属性
foreach (ClassMsgAttribute m in MyAtts)
{
Console.WriteLine("Person类的特性:{0}", m.Msg);
}
GetCustomAttributes用于获取程序集的特性,也就是这个程序集合中包含了多少个特性
继续来一个简单的例子来说明定制特性:
using System;
public class HelpAttribute: Attribute //定制特性相当于一个类
{
//...
}
不管你是否相信,我们上面已经建立了一个定制特性,现在我们可以用它来装饰现有的类就好像我们使用的Obsolete attribute一样。
[Help()]
public class AnyClass
{
//...
}
注意:对于一个特性类使用Attribute后缀是一个惯例。然而,如果不添加编译器会自动添加匹配。
定义或控制特性的使用
AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述一个定制特性如何被使用。
下面通过实例来探讨下AttributeUsage的三个属性
1)我们将会在刚才的Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。
- using System;
- [AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
- Inherited = false ]
- public class HelpAttribute : Attribute
- {
- public HelpAttribute(String Description_in)
- {
- this.description = Description_in;
- }
- protected String description;
- public String Description
- {
- get
- {
- return this.description;
- }
- }
- }
using System;
[AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
Inherited = false ]
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特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:
- [Help("this is a do-nothing class")]
- public class AnyClass
- {
- [Help("this is a do-nothing method")] //error
- public void AnyMethod()
- {
- }
- }
- //编译器报告错误如下:
- 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()
{
}
}
//编译器报告错误如下:
AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.
我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:
Assembly,
Module,
Class,
Struct,
Enum,
Constructor,
Method,
Property,
Field,
Event,
Interface,
Parameter,
Delegate,
All = Assembly Module Class Struct Enum Constructor Method Property Field Event Interface Parameter Delegate,
ClassMembers = Class Struct Enum Constructor Method Property Field Event Delegate Interface )
下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次。
- [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
[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, 表明当特性被放置在一个基类上时,它能否被派生类所继承。
- [Help("BaseClass")]
- public class Base
- {
- }
- public class Derive : Base
- {
- }
- 这里会有四种可能的组合:
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]
[Help("BaseClass")]
public class Base
{
}
public class Derive : Base
{
}
这里会有四种可能的组合:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]
第一种情况:
如果我们查询(Query)(稍后我们会看到如何在运行期查询一个类的特性)Derive类,我们将会发现Help特性并不存在,因为inherited属性被设置为false。
第二种情况:
和第一种情况相同,因为inherited也被设置为false。
第三种情况:
为了解释第三种和第四种情况,我们先来给派生类添加点代码:
[Help("BaseClass")]
public class Base
{
}
[Help("DeriveClass")]
public class Derive : Base
{
}
现在我们来查询一下Help特性,我们只能得到派生类的属性,因为inherited被设置为true,但是AllowMultiple却被设置为false。因此基类的Help特性被派生类Help特性覆盖了。
第四种情况:
在这里,我们将会发现派生类既有基类的Help特性,也有自己的Help特性,因为AllowMultiple被设置为true。
C#特性学习笔记一的更多相关文章
- java8 新特性学习笔记
Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...
- C#特性学习笔记二
实例探讨: 自定义了一个特性类: [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)] class WahAttribute ...
- InnoDB关键特性学习笔记
插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...
- C# 特性学习笔记
1.自己定义的特性 注意注释!!!!! 2.使用特性 3.特性的用处
- Python高级特性学习笔记
切片(slice) 可简化循环取元素的操作. L[0:3] or L[:3] 表示从索引0的位置开始,到索引3为止,但不包括索引3的前3个元素(L[0],L[1],L[2]); L[-2:]表示取包括 ...
- java8新特性学习笔记链接
https://blog.csdn.net/yitian_66/article/details/81010434
- html5新特性学习笔记
1.语义化标签兼容问题(语义化标签只支持ie8以上,不包括ie8) 解决方法一:该标签的css中加上display:block; 通过DOM的方式创建这个标签 document.createEleme ...
- Java8新特性学习笔记(一) Lambda表达式
没有用Lambda表达式的写法: Comparator<Transaction> byYear = new Comparator<Transaction>() { @Overr ...
- Go类型特性-学习笔记
1.组合 Go语言使用组合来完成类型的设计,设计某一类型时想要拥有其他类型的功能只需要将其他类型嵌入该类型即可. 2.接口 与其他语言不同的是,编译器会自动判断该类型是否符合某正在使用的接口,甚至不需 ...
随机推荐
- HTML5 十大新特性(一)——语义标签
说语义标签前先来理解下什么叫语义化,当下html是靠div+css来铸造页面的整体框架和结构的,通篇大量的div可读性极低,因此诞生了这些特殊的标签,简单地说就是见名知义,使页面更清晰,方便维护和开发 ...
- SSH2 框架下的分页
1.设计分页实体(pageBean) 这里我显示的是3-12页的方式: package cn.itcast.oa.domain; import java.util.List; /** * 封装分页信息 ...
- 学习笔记:UpdatePanel控件
Asp.net UpdatePanel 允许用户构建一个丰富的,以客户端为中心的应用程序,引用UpdatePanel控件,能够实现页面的部分刷新,一个包含scriptManage和 UpdatePan ...
- 分治法求2n个数的中位数
问题:设X[0:n-1]和Y[0:n-1]为两个数组,每个数组中含有n个已排好序的数.试设计一个O(logn)时间的分治算法,找出X和Y的2n个数的中位数 思想: 对于数组X[0:n-1]和Y[0:n ...
- google应用商店的解决
{ "enabled_plugins": [ "SimpleReloadPlugin", "SimpleRefresh" ] } git c ...
- xcodebuild
xcodebuild -workspace /path/union/moon-ios/Moon.xcworkspace -scheme Moon ONLY_ACTIVE_ARCH=NO TARGETE ...
- Java:多线程<一>
程序运行时,其实是CPU在执行程序的进程,为了提高工作效率一个进程可以有多个线程. Java的多线程: 其实我们之前就见过Java的线程,main就是Java的一个线程,还有另一个条线程总是和main ...
- html 选择图片后马上展示出来
document.getElementById('file4').onchange = function(evt) { // 如果浏览器不支持FileReader,则不处理 if (!window.F ...
- Java设计模式系列2--工厂方法模式(Factory Method)
2014-02-26 09:56:45 声明:本文不仅是本人自己的成果,有些东西取自网上各位大神的思想,虽不能一一列出,但在此一并感谢! 工厂方法模式分为三种: 1. 普通工厂模式 建立一个工厂类,对 ...
- GIT(分布式版本控制系统)
Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.[1] Git的读音为/gɪt/. Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本 ...