特性

特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。
特性可以当成一个特殊的类看待

列举特性语法:

 [attribute(positional_parameters, name_parameter = value, ...)]
element

attribute为特性名称,positional_parameters, name_parameter是特性属性,value为name_parameter属性的值

三种预定义特性:

.Net Framework 提供了三种预定义的特性:

1. AttributeUsage

该特性描述了用户定义的特性类如何被使用
AttributeUsage基本结构:

 [AttributeUsage( validon,
AllowMultiple=allowmultiple,
Inherited=inherited )]

示例:

 [AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

validon规定了该特性能够被承载,或者说是能够被那些类型所使用的声明,如示例中指明了该特性只能在Class(类),constructor(结构体),Field(字段),Method(方法),Property(属性)
AllowMutiple规定是否能被重复使用,如果为true则能被重复使用
Inherited规定这个特性是否能被派生类继承,默认false不可继承,true则为可继承

2.Conditional

这个预定义特性标记了一个条件方法,其执行依赖于特定的预处理标识符
它会引起方法调用的条件编译,取决于指定的值,比如 Debug 或 Trace。例如,当调试代码时显示变量的值
Conditional的基本结构:

 [
Conditional(
conditionalSymbol
)]

使用示例:

#define hong
using System;
using System.Diagnostics;
public class Myclass
{
[Conditional("hong")] //预定义的Conditional特性
public static void Message(string msg)
{
Console.WriteLine(msg);
}
}
class Test
{
static void function1()
{
Myclass.Message("In Function 1.");
function2();
}
static void function2()
{
Myclass.Message("In Function 2.");
}
public static void Main()
{
Myclass.Message("In Main function.");
function1();
}
}

该程序预定义了一个宏:hong,Conditional特性在函数Message中被使用:[Conditional("hong")] 如果没有该宏定义则不会执行函数Message

1. 若定义了宏则程序如上,运行:(Message会被调用)

In Main function.
In Function 1.
In Function 2.
C:\C#\code\Conditional\bin\Debug\netcoreapp3.0\Conditional.exe (进程 18092)已退出,返回代码为: 0。
若要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口...

2. 若将第一行定义宏注释:

//#define hong
using System;
using System.Diagnostics;

运行(此时Message函数不会被调用,则没有输出):

C:\C#\code\Conditional\bin\Debug\netcoreapp3.0\Conditional.exe (进程 18264)已退出,返回代码为: 0。
若要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口...
3.Obsolete

这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为 obsolete(过时的)。
Obsolete特性结构:

 [Obsolete(
message )] [Obsolete(
message,
iserror )]

message:为描述文字,不使用该函数的原因以及替换函数
iserror:为bool值,true则编译器会把引用了该特性的项目当成错误,产生编译器警告

示例:

    using System;
public class MyClass
{
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod()
{
Console.WriteLine("It is the old method");
}
static void NewMethod()
{
Console.WriteLine("It is the new method");
}
public static void Main()
{
OldMethod();
}
}

运行编译器会提示错误:

 Don't use OldMethod, use NewMethod instead

创建自定义特性的步骤:

  • 声明自定义特性
  • 构建自定义特性
  • 在目标程序元素上应用自定义特性
  • 通过反射访问特性

详细示例在学习完反射后一同进行

反射

反射(Reflection) 对象用于在运行时获取类型信息。该类位于 System.Reflection 命名空间中,可访问一个正在运行的程序的元数据。
System.Reflection 命名空间包含了允许您获取有关应用程序信息及向应用程序动态添加类型、值和对象的类。

反射(Reflection)有下列用途:

  1. 它允许在运行时查看属性(attribute)信息。
  2. 它允许审查集合中的各种类型,以及实例化这些类型。
  3. 它允许延迟绑定的方法和属性(property)。
  4. 它允许在运行时创建新类型,然后使用这些类型执行一些任务。

查看元数据

using System;
[AttributeUsage(AttributeTargets.All)] //规定了特性的能承载所有类型
public class HelpAttribute : System.Attribute //自定义特性HelpAttribute继承自Attribute基类
{
public readonly string Url;
public string Topic // Topic 是一个表示名字的参数
{
get
{
return topic;
}
set
{
topic = value;
}
}
public HelpAttribute(string url) // url 是一个表示位置的参数
{
this.Url = url;
}
private string topic;
}
public class OtherAttribute : System.Attribute
{
public string topic2
{
get
{
return topic2;
}
set
{
topic2 = value;
}
}
}
[HelpAttribute("Information on the class MyClass")] //特性被应用到MyClass一个空类中
[OtherAttribute()] //第二个特性
class MyClass
{ } namespace AttributeAppl
{
class Program
{
static void Main(string[] args)
{
System.Reflection.MemberInfo info = typeof(MyClass); //System.Reflection.MemberInfo初始化
object[] attributes = info.GetCustomAttributes(true); //获取目标类(MyClass)所承载的特性
for (int i = ; i < attributes.Length; i++) //遍历所有特性
{
System.Console.WriteLine(attributes[i]);
}
}
}
}

System.Reflection.MemberInfo info = typeof(MyClass);          
System.Reflection.MemberInfo需要初始化,用于与目标类关联(MyClass)

结果:(返回了MyClass类所承载的两个特性)

HelpAttribute
OtherAttribute C:\C#\code\Feflection\bin\Debug\netcoreapp3.0\Feflection.exe (进程 6244)已退出,返回代码为: 0。
若要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口...

利用特性设置声明信息并用反射进行访问

using System;
using System.Reflection;
namespace attribute
{
[AttributeUsage(AttributeTargets.Class| //声明自定义特性,描述自定义特性DebugInfo如何被使用
AttributeTargets.Constructor|
AttributeTargets.Field|
AttributeTargets.Method|
AttributeTargets.Property,
AllowMultiple =true)]
public class DebugInfo : Attribute //构建自定义特性
{
private int bugNo; //bug number
private string developer;
private string lastReview; //last reviewed
public string message;
public DebugInfo(int BN,string D,string LR) //构造函数
{
this.bugNo = BN;
this.developer = D;
this.lastReview = LR;
}
public int BugNo
{
get
{
return bugNo;
}
}
public string Developer
{
get
{
return developer;
}
}
public string LastReview
{
get
{
return lastReview;
}
}
public string Message
{
set
{
message = value;
}
get
{
return message;
}
}
}
[DebugInfo(,"asahi","19/5/1",Message ="can't return type")] //在目标程序元素上应用自定义特性
[DebugInfo(,"Lock","19/9/9",Message ="unable variable")]
class Rectangle //矩形类,承载了两个特性
{
protected double length;
protected double width;
public Rectangle(double L,double W)
{
this.length = L;
this.width = W;
}
[DebugInfo(,"sayo","19/9/15",Message ="return false")]
public double getArea()
{
return length * width;
}
[DebugInfo(,"katsumi","19/10/1",Message ="output error")]
public void Display()
{
Console.WriteLine("Length={0}", length);
Console.WriteLine("Width={0}", width);
Console.WriteLine("Area={0}", getArea());
}
}
class Program
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(, );
r.Display(); Type type = typeof(Rectangle); //获取Rectangle的类型
//遍历Rectangle特性
Console.WriteLine(" Rectangle类型的特性测试:");
foreach(object attributes in type.GetCustomAttributes(false)) //获取Rectangle类型的所有特性,迭代的方式赋予attributes
{
DebugInfo debugInfo = (DebugInfo)attributes; //所有特性转换为DebugInfo类型
if (debugInfo != null)
{
Console.WriteLine("Debug number:{0}", debugInfo.BugNo);
Console.WriteLine("Developer:{0}", debugInfo.Developer);
Console.WriteLine("Last Review:{0}", debugInfo.LastReview);
Console.WriteLine("Message:{0}\n", debugInfo.Message);
}
} Console.WriteLine(" Rectangle类型的所有函数的特性测试:");
//遍历方法属性
foreach(MethodInfo m in type.GetMethods()) //遍历type类型即Rectangle类型所有函数
{
foreach(object attributes in m.GetCustomAttributes(false)) //遍历每个函数的特性
{
DebugInfo debugInfo = (DebugInfo)attributes;
if (debugInfo != null)
{
Console.WriteLine("Debug number:{0}", debugInfo.BugNo);
Console.WriteLine("Developer:{0}", debugInfo.Developer);
Console.WriteLine("Last Review:{0}", debugInfo.LastReview);
Console.WriteLine("Message:{0}\n", debugInfo.Message);
}
}
}
}
}
}

结果:

Length=
Width=
Area=
Rectangle类型的特性测试:
Debug number:
Developer:asahi
Last Review://
Message:can't return type Debug number:
Developer:Lock
Last Review://
Message:unable variable Rectangle类型的所有函数的特性测试:
Debug number:
Developer:sayo
Last Review://
Message:return false Debug number:
Developer:katsumi
Last Review://
Message:output error C:\Program Files\dotnet\dotnet.exe (进程 )已退出,返回代码为: 。
若要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口...

参考链接:

https://www.w3cschool.cn/wkcsharp/8jib1nvi.html

https://www.w3cschool.cn/wkcsharp/9phg1nvl.html

C# 特性和索引(C#学习笔记06)的更多相关文章

  1. 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记

    机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习作者:米仓山下时间: ...

  2. iOS学习笔记06—Category和Extension

    iOS学习笔记06—Category和Extension 一.概述 类别是一种为现有的类添加新方法的方式. 利用Objective-C的动态运行时分配机制,Category提供了一种比继承(inher ...

  3. MySQL索引知识学习笔记

    目录 一.索引的概念 二.索引分类 三.索引用法 四 .索引架构简介 五.索引适用的情况 六.索引不适用的情况 继我的上篇博客:Oracle索引知识学习笔记,再记录一篇MySQL的索引知识学习笔记,本 ...

  4. Oracle索引知识学习笔记

    目录 一.Oracle索引简介 1.1 索引分类 1.2 索引数据结构 1.3 索引特性 1.4 索引使用注意要点 1.5.索引的缺点 1.6.索引失效 二.索引分类介绍 2.1.位图索引 1.2.函 ...

  5. [Golang学习笔记] 06 程序实体3 类型断言和类型转换

    类型断言: 语法:<目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言<目标类型的值> := <表达式>. ...

  6. stm32寄存器版学习笔记06 输入捕获(ETR脉冲计数)

    STM32外部脉冲ETR引脚:TIM1-->PA12;TIMER2-->PA0:TIMER3-->PD2;TIMER4-->PE0… 1.TIM2 PA0计数 配置步骤 ①开启 ...

  7. [原创]java WEB学习笔记06:ServletContext接口

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  8. Bash脚本编程学习笔记06:条件结构体

    简介 在bash脚本编程中,条件结构体使用if语句和case语句两种句式. if语句 单分支if语句 if TEST; then CMD fi TEST:条件判断,多数情况下可使用test命令来实现, ...

  9. OpenCV 学习笔记 06 图像检索以及基于图像描述符的搜索

    OpenCV 可以检测图像的主要特征,然后提取这些特征,使其成为图像描述符,这些图像特征可作为图像搜索的数据库:此外可以利用关键点将图像拼接 stitch 起来,组成一个更大的图像.如将各照片组成一个 ...

随机推荐

  1. 逆向破解之160个CrackMe —— 023-024

    CrackMe —— 023 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...

  2. java Atomic compareAndSet部分原理分析

    以AtomicLong的compareAndSet方法举例.先说结论:如果CPU支持,则基于CPU指令(CMPXCHG8)实现:否则使用ObjectLocker锁实现. 分析过程如下: 该方法在jdk ...

  3. 洛谷P4549 裴蜀定理 / Min

    原题链接 题目描述 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1X1+...AnXn>0,且S的值最小 输入输出格式 输入格式: 第一行给出数字N,代表有N个数 下 ...

  4. 23-C#笔记-正则表达式

    等用的时候,可以现查. 参考: http://www.runoob.com/csharp/csharp-regular-expressions.html

  5. Gartner:2019 年 iPaaS 魔力象限

    http://www.199it.com/archives/869090.html 企业iPaaS产品支持越来越更广泛的使用场合,正迅速被企业采用以实现混合集成平台策略.这份魔力象限评估了17家供应商 ...

  6. NOIP 2015 推销员

    洛谷 P2672 推销员 洛谷传送门 JDOJ 2994: [NOIP2015]推销员 T4 JDOJ传送门 Description 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死 ...

  7. Elasticsearch的null values

    很多时候,我们需要面临null值的烦扰,查询es时传入null值是要查询出null的数据还是不查这个field呢,稍有不慎就会引发新的bug,这的确是个问题! null_value 意味着无法索引或搜 ...

  8. Springboot之自定义配置

    SpringBoot自定义配置 springboot在这里就不过多介绍了,大家都应该了解springboot零配置文件,所以配置信息都装配在属性文件(properties.yml.yaml)中,有时我 ...

  9. 第01组 Alpha冲刺(5/6)

    队名:007 组长博客: https://www.cnblogs.com/Linrrui/p/11901035.html 作业博客: https://edu.cnblogs.com/campus/fz ...

  10. 深入理解 HTTP/1.x、HTTP/2 和 HTTPS

    很多站长可能到现在都没有理解 HTTP/1.x.HTTP/2 和 HTTPS 之间的区别和关系吧?说实话,明月也是“一知半解”的水准而已,今天看到了这篇文章感觉总结还算是比较全面,特此分享出来给大家就 ...