特性

特性(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. 【Servlet】Servlet的配置

    创建时间:6.15 Servlet的配置 1. 基本配置 其中url-pattern的配置方式: 1)完全匹配 访问的资源与配置的资源完全相同才能访问到 2)目录匹配 格式:/虚拟的目录../*   ...

  2. angular-依赖注入 显示注入/隐式注入

    1.隐式注入:不需要开发人员干预,angularJS自动根据参数的名称识别和注入数据 app.controller("myCtrl".function($scope) { $sco ...

  3. HLOJ1361 Walking on the Grid II 矩阵快速幂

    题目分析: 就当是一次记录吧,2013年绍兴市市赛的一题,重现赛当时我想递推可能是矩阵快速幂吧,但是这个递推公式真没推出来(赛后猛如虎系列),这题和第一题有联系又有区别,第一题的递推很简单,dp[i] ...

  4. PHP中md5()函数绕过

    PHP md5()函数的简单绕过方法,该篇作为学习笔记简单记录一下.   例题   例题链接: http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php   ...

  5. 3.创建Manager类,演示对TestUser进行增删改查功能

    接上一篇文章 创建NHibernateHelper帮助类,生成sessionFactory http://www.cnblogs.com/fzxiaoyi/p/8443587.html 创建个新的类M ...

  6. django 修改 request 对象中的请求参数, 并重新赋值给 request 对象

    直接上代码, 实现流程看代码及注释 def your_view(self, request): method = request.method if method == "GET" ...

  7. JavaScript基础09——事件驱动

    1.事件驱动 js控制页面的行为是由事件驱动的.          什么是事件?(怎么发生的)     事件就是js侦测到用户的操作或是页面上的一些行为       事件源(发生在谁身上)     引 ...

  8. Oracle EBS11i的下载

    1.登陆Oracle eDelivery https://edelivery.oracle.com/osdc/faces/Home.jspx 2.需要账号登录才能进行下载 chaomu@css.com ...

  9. Struts CRUD

    Struts CRUD 利用struts完成增删改查 思路: 1.导入相关的pom依赖(struts.自定义标签库的依赖) 2.分页的tag类导入.z.tld.完成web.xml的配置 3.dao层去 ...

  10. django -- ORM建表

    前戏 ORM(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. ORM的优势: ORM解决的主要问题是对象和关系的映射 ...