特性Attribute
什么是特性
特性是一种允许我们向程序的程序集增加元数据的语言结构,它是用于保存程序结构信息的某种特殊类型的类
- 拥有特性的代码程序叫做 目标
- 获取和使用元数据的代码程序叫做 特性的消费者
编译器获取源代码并从特性中产生元数据,然后把元数据放到程序集中;
消费者程序 可以获取特性的元数据以及程序中其他组件的元数据,即编译器同时生产和消费特性
使用前置 特性片段 来应用特性,特性片段被方括号包围,方括号中为 特性名 和 特性的参数列表
我们可以使用 assembly: 和 module: 来设定全局特性,即程序集或块级别,程序集级别的特性一般都要放置在如何命名空间之外,通常放置在 AssemblyInfo.cs 文件中
以上来自原文链接:https://blog.csdn.net/qq_38801354/article/details/79884391
Obsolete
有时候版本更新,旧方法被弃用,可以用Obsolete表示这个方法已被启用
使用方法:
[obsolete(参数1,参数2)] 参数1表示调用时提示的信息,参数2表示是否提示错误
示例代码:
[Obsolete("该方法已过时,可用NewMethod代替",true)]//true表示调用时出现的是错误而不是警告 static void OldMethod() { Console.WriteLine("旧方法"); } static void NewMethod() { Console.WriteLine("新方法"); }
Conditional
有时候我们项目未上线前或者测试时需要使用一些测试方法,加上Conditional特性可以帮助我们更好的调试程序。
使用方法:
在最上面添加一个宏定义
#define IsTest
引入命名空间:
using System.Diagnostics
在方法上面加入[Conditional(“IsTest”)]
示例代码:
#define IsTest //宏定义,用于测试。注释后相关方法将不可用 using System; using System.Diagnostics;//Conditional用 namespace Conditional { class Program { static void Main(string[] args) { TestMethod(); Method(); } [Conditional("IsTest")] static void TestMethod() { Console.WriteLine("这是一段测试代码"); } static void Method() { Console.WriteLine("正式代码"); } } }
TestMethod()就是我们要用于测试的方法,当我们不需要使用这个方法时,只要将#define IsTest注释掉,程序运行时就不会跳过TestMethod()的调用。
调用信息特性
如果我们需要得到方法的调用者信息,可以使用:
[Caller.......],直接上代码好理解点:
static void Main(string[] args) { string str = "lzx`s File"; TestMethod(str); } static void TestMethod(string str,[CallerFilePath] string fileName="",[CallerLineNumber]int lineNumber=0,[CallerMemberName]string methodName="") { Console.WriteLine(str); Console.WriteLine(fileName); Console.WriteLine(lineNumber); Console.WriteLine(methodName); }
输出:
DebuggerStepThrough特性
这个相对简单,只要在方法上面加入[DebuggerStepThrough]特性,在调试时就会跳过该方法的单步调试,但我们确定这个方法没有错误的时候,就可以使用这个特性简化我们的调试过程。
比如上面的TestMethod方法:
[DebuggerStepThrough]//调试时跳过该方法内的单步调试 static void TestMethod(string str,[CallerFilePath] string fileName="",[CallerLineNumber]int lineNumber=0,[CallerMemberName]string methodName="") { Console.WriteLine(str); Console.WriteLine(fileName); Console.WriteLine(lineNumber); Console.WriteLine(methodName); }
其他特性
自定义特性Attribute
特性其实就是一种特殊的类,所以自定义特性其实也是一种继承自Attribute的类。以下是它的一些特点:
- 特性类的后缀以Attribute结尾
- 需要继承自system.Attribute
- 一般情况下声明为sealed
- 一般情况下 特性类是用来表示目标结构的一些状态(定义一些字段或者属性,一般不定义方法)
举个例子,我们自定义了一个MyTestAttribute特性
sealed class MyTestAttribute:Attribute { public string Desription { get; set; }//特性的描述 public string VersionNumber { get; set; }//版本 public int ID { get; set; } //特性的使用可以简单理解为每次使用特性类,这里我们简单定义了以下这个构造函数。当然可以不定义构造函数,这样系统就会调用预定义的无参无实现的构造函数 //public MyTestAttribute(string des) //{ // this.Desription = des; //} }
指定Program为MyTestAttribute特性:
[MyTest(Desription = "lzx", ID = 1, VersionNumber = "ss")]//使用匿名参数赋值 class Program { ...... }
此时我们就可以在Main中使用Type取得特性的成员了:
Program pro = new Program(); Type type = pro.GetType(); object[] array = type.GetCustomAttributes(false);//两个注意点:一是使用Object类 //二是GetCustomAttributes(),这个方法是使用了反射来搜索该类所具有的所有的特性;输入的参数,false表示不去搜索其父类中的所具有的特性 foreach(MyTestAttribute my in array) { Console.WriteLine(my.ID); }
还有一种方法,可以直接获取特性中的某个成员:
var myTestID = (type.GetCustomAttributes(TypeOf(MyTestAttribute),false)[0] as MyTestAttribute).ID;
这种方法适用于已知成员的索引。