C# 特性和索引(C#学习笔记06)
特性
特性(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)有下列用途:
- 它允许在运行时查看属性(attribute)信息。
- 它允许审查集合中的各种类型,以及实例化这些类型。
- 它允许延迟绑定的方法和属性(property)。
- 它允许在运行时创建新类型,然后使用这些类型执行一些任务。
查看元数据
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)的更多相关文章
- 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记
机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习作者:米仓山下时间: ...
- iOS学习笔记06—Category和Extension
iOS学习笔记06—Category和Extension 一.概述 类别是一种为现有的类添加新方法的方式. 利用Objective-C的动态运行时分配机制,Category提供了一种比继承(inher ...
- MySQL索引知识学习笔记
目录 一.索引的概念 二.索引分类 三.索引用法 四 .索引架构简介 五.索引适用的情况 六.索引不适用的情况 继我的上篇博客:Oracle索引知识学习笔记,再记录一篇MySQL的索引知识学习笔记,本 ...
- Oracle索引知识学习笔记
目录 一.Oracle索引简介 1.1 索引分类 1.2 索引数据结构 1.3 索引特性 1.4 索引使用注意要点 1.5.索引的缺点 1.6.索引失效 二.索引分类介绍 2.1.位图索引 1.2.函 ...
- [Golang学习笔记] 06 程序实体3 类型断言和类型转换
类型断言: 语法:<目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言<目标类型的值> := <表达式>. ...
- stm32寄存器版学习笔记06 输入捕获(ETR脉冲计数)
STM32外部脉冲ETR引脚:TIM1-->PA12;TIMER2-->PA0:TIMER3-->PD2;TIMER4-->PE0… 1.TIM2 PA0计数 配置步骤 ①开启 ...
- [原创]java WEB学习笔记06:ServletContext接口
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- Bash脚本编程学习笔记06:条件结构体
简介 在bash脚本编程中,条件结构体使用if语句和case语句两种句式. if语句 单分支if语句 if TEST; then CMD fi TEST:条件判断,多数情况下可使用test命令来实现, ...
- OpenCV 学习笔记 06 图像检索以及基于图像描述符的搜索
OpenCV 可以检测图像的主要特征,然后提取这些特征,使其成为图像描述符,这些图像特征可作为图像搜索的数据库:此外可以利用关键点将图像拼接 stitch 起来,组成一个更大的图像.如将各照片组成一个 ...
随机推荐
- Linux的rpm管理
书山有路勤为径,学海无涯苦作舟 自学linux已经有几天了,感觉还可以.坚持下去,就会有收获. 每个系统都用相应的软件的管理,Linux也不例外.下面讲 ...
- Redis开启远程访问及密码
一.开启远程访问 1.开放端口 firewall-cmd --zone=public --add-port=6379 firewall-cmd --zone=public --add-port=637 ...
- 采坑复盘:logging日志能用封装后的函数来打日志,发现filename一直显示封装logging函数的方法所在的文件名
问题: logging日志能用封装后的函数来打日志,发现filename一直显示封装logging函数的方法所在的文件名 原因: logging记录的是第一个函数执行所在的文件,那用封装的函数,首先执 ...
- discuz开发实现自动获取后台入口代码
一般discuz后台入口默认是admin.php,不过部分用户为了安全可能会修改后台入口文件名称,可以用代码 '.ADMINSCRIPT.'?frame=no&action=tools& ...
- opencart中文版checkout设置city和county为非必选
opencart中文版在opencart原版进行了一些修改,添加了适合国内使用的设置,但是并不适合国外用户,比如订单页面的收货地址添加了国内的城市和区县,而国外的city和county被删减了,这两项 ...
- 重新学习Spring注解——ICO
02.组件注册-@Configuration&@Bean给容器中注册组件 03.组件注册-@ComponentScan-自动扫描组件&指定扫描规则 04.组件注册-自定义TypeFil ...
- 用JSON.parse(JSON.stringify(itemData))序列化反序列化实现‘深度复制’
还可以用来去除值不具有JSON 表示形式(数字.字符串.逻辑值.数组.对象.null)的属性,也就是说像undefined和function这样的属性值.
- Kubernetes安全策略
Kubernetes CIS Benchmark 见kube-bench 1.安全策略 1.1 使用宿主节点的命名空间 命名空间分 网络命名空间 PID命名空间 IPC命名空间 Pod使用主机的网络命 ...
- 数据库: 安装配置数据库,使用Navicat for MySQL和手机APP 连接测试(如果上一节碰到问题可参考这一节)
咱就安装上 还有这个 最终测试请参考上一节 启动MySQL服务主要有以下两种方法: 第一种: 在搜索框中输入“services,msc” ,en ...
- 洛谷P1230智力大冲浪 题解
题目描述 小伟报名参加中央电视台的智力大冲浪节目.本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元.先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则: ...