Attribute

不打扰是莪最后的温柔 提交于 2020-04-06 07:00:18

文章著作权归作者所有。转载请联系作者,并在文中注明出处,给出原文链接。
本文原更新于作者的github博客,这里给出链接

[Obsolete]
public static void Func() {
    // ...
}

Attribute是什么

注释是对程序源代码的一种说明,在编译时会被编译器丢弃,不会影响程序的执行,但有时候我们希望“注释”可以影响到程序。这个时候,Attribute就派上用场了。Attribute(特性)是一种语言构造(language construct),它允许你向程序集里添加元数据,是程序代码的一部分。

Attribute的形式

Attribute在形式上像是Property、Method、Class的一个装饰或者标签,但实质上它是一个实例化方式特殊的类,它必须依附在一个target上,它一般安放在这些target的上方,在方括号内声明。获取和使用元数据的程序被称为consumer。一个target可以拥有多个Attribute,Attribute的顺序不会影响效果。

Attribute的使用

在使用Attribute时,我们可以使用Attribute的全称,也可以使用Attribute的前缀。使用无参Attribute时,可以省略参数列表的括号。

// both are supported
[Obsolete]
public static void Func() {
    // ...
}
[ObsoleteAttribute]
public static void Func() {
    // ...
}

也可以在同一个target上使用多个Attribute。

[Obsolete]
[Serializable]
public static void Func() {
    // ...
}

Predefined Attribute

.NET为我们提供了一些预定义的Attribute,如:

[Obsolete]:需要using System;

作用:提示这个方法已经过时,但还没有被系统丢弃,给出warning。

Obsolete的构造方法:public ObsoleteAttribute(string message = "", bool isError = false)

其中message是反馈给方法调用者的指示信息,isError为真时,这个弃用会升级为报错。

using System;

public class Test {
	// 调用警告
    [Obsolete("Use SuperPrint instead")]
	static void Print() {
		// using System
		Console.WriteLine("Print");
	}
	
	// 调用报错
	[Obsolete("Use SuperPrint instead", true)]
	static void PrintSomething(string something) {
		Console.WriteLine(something);
	}
}

[Conditional]:需要using System.Diagnostics

作用:通过预处理指令选择性编译代码

target:1.返回类型为void的方法,但不能是重写方法,可以是虚函数;2.继承自Attribute的类

Conditional的构造方法:public ConditionalAttribute(string header)

其中header是预编译指令,若这个程序包含header,则编译这个方法,否则完全忽略。

// 预编译头必须在所有代码之前声明
#define CALL
using System;
using System.Diagnostics;

public class Test {
	// 因为包含了CALL指令,这个方法会被编译
    [Conditional("CALL")]
    public void Call() {
        Console.WriteLine("This Method is being called");
    } 
}

自定义Attribute

前面提到,Attribute是一种特殊的类,他们都继承自Attribute基类,我们也可以通过继承的方式定义自己的Attribute。

// 自定义Attribute
// 继承System.Attribute基类
// 这个类的名称必须以Attribute为后缀
// 使用不带参数的Attribute时可省略构造方法的括号
// 一个Attribute类通常只需要包含字段,变量以及构造方法,并且至少包含一个公开的构造方法
// - sealed 相当于Java的final
// AttributeUsage可以限制使用此属性的类型,全类型为All,多类型复合用按位或运算符
// AttributeTargets是一个enum类型,里面规定了target的类型以及对应的二进制码
// AttributeUsage的第二个参数规定这个Attribute是否可继承,默认是
// 第三个参数规定一个类型是否可以挂载多个此Attribute的实例,默认否

// 声明了一个叫MyAttri的Attribute,它的target只能是Property或者Method
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
public sealed class MyAttriAttribute : Attribute {

	private string name;
	private int index;
	
	public MyAttriAttribute(string _name = "", int _index = 0) {
		name = _name;
		index = _index;
	}
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!