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 起来,组成一个更大的图像.如将各照片组成一个 ...
随机推荐
- Ajax请求设置csrf_token
方式1 通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送. $.ajax({ url: "/cookie_ajax/", type: ...
- 大数据技术原理与应用【第五讲】NoSQL数据库:5.6 文档数据库MongoDB
文档数据库介于关系数据库和NoSql之间: 是最像关系数据库的一款产品,也是当前最热门的一款产品. 1.MongoDB简介: 1) 2)文档类型BSON(Binary JSON),结构类似 ...
- Extended Traffic LightOJ - 1074
题目链接:https://vjudge.net/problem/LightOJ-1074 思路:(busyness of destination - busyness of source)3 可能会是 ...
- Leetcode79 Word Search
题目描述 Given a 2D board and a word, find if the word exists in the grid. The word can be constructed f ...
- django 权限设置 左侧菜单点击显示,面包屑
1.左侧菜单点击显示 就是在点击的时候保留点击的功能 方法. 1.加入新的字段,pid来判断 class Permission(models.Model): """ 权限 ...
- CodeForces 150E: Freezing with Style
题目传送门:CF150E. 据说这个傻逼题还有一个 \(\log\) 的做法,但是我还不会. 题意简述: 给定一棵 \(n\)(\(2\le n\le 10^5\))个点的树,边有边权. 定义一条路径 ...
- JMeter5.1开发SMTP协议接口脚本
jmeter可以测试发邮件和读取邮件. 发送邮件 上图部分解释: Server:邮件发送服务 Port:发邮件端口,不加密25,加密465,如果是465端口,Security settings 需要选 ...
- python将数组写入文件
import numpy as npdata = np.array([[1,2], [3,4]]) np.savetxt('out.txt', data, fmt="%d") #保 ...
- python相对导包问题
导包分为:绝对路径.相对路径 在测试时发现不能够使用相对路径 查过之后才知道: 运行模块(如:main.py)中导包只能使用绝对路径,不能使用相对路径 官方文档: Note that relative ...
- mac 下使用nasm
#安装nasm brew install nasm #创建文件 vi hello.asm 写入如下内容 msg: db "hello world!", 0x0a len: equ ...