特性
概念:特性是一种允许我们向程序的程序集添加元数据的语言结构,是用于保存程序结构信息的某种特殊类型的类。特性提供功能强大的方法以将声明信息与C#代码(类型、方法、属性等)相关联。特性与程序实体关联后,即可在运行时使用反射查询特性信息。特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集中,可以放置在几乎所有的声明中(类、变量、函数等)。
可以理解为特性是一个特殊的继承自Attribute的类,用来为元数据添加信息,然后通过反射来获取这些信息。
自定义特性:
语法:
class MyCustomAttribute : Attribute
{
//特性成员
public string info;
public MyCustomAttribute(string info)
{
this.info = info;
}
public void TestFun()
{
Console.WriteLine("这是特性中的方法");
}
}
特性的使用:
本质上是调用特性类的构造函数。
位置:类、函数、变量的上一行,表示他们具有该特性。
语法:
[特姓名(参数列表)]
[MyCustom("这是一个自定义类")]
class Test
{
[MyCustom("这是一个成员变量")]
public string info;
[MyCustom("这是一个成员函数")]
public void TestFun([MyCustom("函数参数")]int i)
{
}
}
internal class Program
{
static void Main(string[] args)
{
//特性的使用
Test test = new Test();
//三种获得Type的方式
Type t = typeof(Test);
t = Type.GetType("L21_特性.Test");
t = test.GetType();
//使用一:用来判断是否使用了某个特性;
//参数一:特性的Type类型;参数二:是否搜索继承链(属性和事件忽略此参数)
if (t.IsDefined(typeof(MyCustomAttribute), false))
{
Console.WriteLine("该类型应用了MyCustom特性");
}
//使用二:获取元数据中的所有特性,可以执行方法。
object[] objects = t.GetCustomAttributes(true);
for (int i = 0; i < objects.Length; i++)
{
if (objects[i] is MyCustomAttribute)
{
Console.WriteLine((objects[i] as MyCustomAttribute).info);
(objects[i] as MyCustomAttribute).TestFun();
}
}
}
}
限制自定义特性的使用范围:
为自定义的特性类添加特性就可以先限制特性类的使用范围。
语法:
//参数一:AttributeTargets —— 特性能够使用的位置
//参数二:AllowMultiple —— 是否允许多个特性实例用在同一目标上
//参数三:Inherited —— 特性是否能被派生类和重写成员继承
//此处写法是通过属性来初始化
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct,AllowMultiple = true,Inherited = true)]
public class MyCustomAttribute2:Attribute
{
}
系统自带特性——过时特性:
关键字:obsolete
使用:用于提示用户使用的方法等成员已经过时,建议使用新方法。
一般用于函数。
实例:
class Test1
{
//参数一:提示的内容
//参数二:true —— 使用该方法时直接报错;false —— 使用该方法时警告
[Obsolete ("这个方法已经过时了,请使用speak方法",false)]
public void OldSpeak() { }
public void Speak() { }
}
系统自带特性——调用者信息特性:
作为函数参数的特性,可以得到具体的信息,通过函数打印出来。
需要应用命名空间。
一般用于作为函数参数的特性,或者try catch的catch中,用于查错误的位置。
[CallerFilePath] —— 哪个文件调用
[CallerLineNumber] —— 哪一行调用
[CallerMemberName] —— 哪个函数调用
实例:
class Test1
{
public void Speak2(string str1, [CallerFilePath] string filePath = "", [CallerLineNumber] int line = 0,
[CallerMemberName]string target = "")
{
Console.WriteLine(str1);
Console.WriteLine(filePath);
Console.WriteLine(line);
Console.WriteLine(target);
}
}
static void Main(string[] args)
{
//系统自带特性——调用者信息特性
Test1 test1 = new Test1();
test1.Speak2("hahahah");
}
系统自带特性——条件编译特性:
语法:[Conditional(“define定义的符号”)]
使用:主要用于需要调试的代码上,和预处理指令#define配合使用。
当函数的条件编译特性参数与define定义的符号相同时,可以执行该函数,否则不会执行。
系统自带特性——外部dll包函数特性:
语法:[DllImport(“文件名或路径名”)]
作用:一般用来调用C或C++的Dll包写好的方法
需要引用命名空间:using System.Runtime.InteropServices;