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开发uboot启动过程源码分析(一)
一.uboot启动流程简介 与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段.BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言 ...
- CEF 3.2623使用flash插件的方法
PPAPI Flash插件是Chrome浏览器内置的Flash插件,是Google和Adobe合作的产物,于Chrome21(Win)或者Chrome20(Linux)加入,具有沙箱.GPU加速.多进 ...
- Mybatis-plus中不列出全部字段
//不列出全部字段 @Test public void test10() { QueryWrapper<User> wrapper = new QueryWrapper<>() ...
- 重新学习Spring注解——声明式事务
36.声明式事务-环境搭建 37.声明式事务-测试成功 38.[源码]-声明式事务-源码分析 /** * 声明式事务: * * 环境搭建: * 1.导入相关依赖 * 数据源.数据库驱动.Spring- ...
- java 8 学习二(Lambda表达式)
粗略的概括:lambda表达式主要用来实现“函数接口”中“唯一”的抽象方法用的. 他的特殊版有 方法引用,构造函数引用,用对应的接口实例接收即可. 可以把Lambda表达式理解为简洁地表示可传递的匿名 ...
- 掌握Visual Studio断点
我知道你现在在想什么.断点?真的吗?关于断点有什么需要掌握的?你按F9然后停在代码行.如果你是这么想的,这篇文章是给你的:继续读 Visual Studio提供了一组相当丰富的断点类型和操作,可以使您 ...
- GitHub 干货 | 各大数据竞赛 Top 解决方案开源汇总
AI 科技评论编者按:现在,越来越多的企业.高校以及学术组织机构通过举办各种类型的数据竞赛来「物色」数据科学领域的优秀人才,并借此激励他们为某一数据领域或应用场景找到具有突破性意义的方案,也为之后的数 ...
- wkhtmltopdf cpdf HTML转pdf 及pdf合并
将 html 转为 pdf :wkhtmltopdf wkhtmltopdf 是一个使用 webkit 网页渲染引擎开发的用来将 html 转成 pdf 的工具,可以跟多种脚本语言进行集成来转换文档. ...
- 区间dp提升复习
区间\(dp\)提升复习 不得不说这波题真的不简单... 技巧总结: 1.有时候转移可以利用背包累和 2.如果遇到类似区间添加限制的题可以直接把限制扔在区间上,每次只考虑\([l,r]\)被\([i, ...
- 基于32位Windows2003的数据库服务器优化,启用AWE,优化SQL Server
最近几天,笔者所在的单位中的一台WEB服务器由于负载过大出现了问题,当同时在线的用户达到一定规模(2000-3000)时,频繁出现页面响应迟缓.超时等问题.服务器采用的操作系统是Windows Ser ...