首页 > 代码库 > C#特性

C#特性

什么是特性,我自己的理解是:

特性是一种允许我们向程序集增加元数据的语言结构。它是用于保存程序结构信息的特殊的类。特性有2个基本概念:“目标”,“消费者”,就拿特殊性DebuggerStepThrough来说,编译器就是消费者,当它遇到被此特性注册过的Mothed时,就不会进入此Mothed执行(断点时)会直接得到此Methed的运行结果,而次Method就是目标了。总而言之,应用了特性的语言结构叫“目标”;设计用来获取和使用此特性的就叫“消费者”。

下面讲解.Net自带的几个比较著名的特性

1,Obsolete : 提示Method过时

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AtrributeTest.com
{
    /// <summary>
    /// 用于测试Obsolete特性
    /// 目标:Method
    /// 消费者 : IDE
    /// </summary>
    public sealed class ObsoleteTest
    {
        [Obsolete("这个方法已经过时,请使用MyNewMethod方法",false)]
        public void MyOldMethd()
        {
            Console.WriteLine("这是一个过时的方法");
        }
        public void MyNewMethod()
        {
            Console.WriteLine("这是一个新方法");
        }
    }
}

测试:

技术分享

可以看出当IDE跳出提示时,会自动在有“Obsolete”标志的Method上划一横线(表示不提倡使用),我在Obsolete的构造函数中提示“这个方法已经过时,请使用MyNewMethod方法”也只IDE提示中显示出来。关于Obsolete的第二个参数(Boolean),它表是“是否不能使用”。如果为true,当使用了MyOldMethd方法后,编译会报错;反之(False的情况),只是不提倡使用。


2,Conditional : 取消Method的任何调用

这个的话我认为并没有编译参数好用。我先放测试代码,再给出解释

1,此内中有一个方法“MyTestMethod”被Conditional特性修饰

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace AtrributeTest.com
{
    /// <summary>
    /// 用于测试Condition特性
    /// 目标:Method
    /// 消费者 : IDE(将影响编译)
    /// </summary>
    public sealed class ConditionalTest
    {
        [Conditional("IsTest")]
        public void MyTestMethod()
        {
            Console.WriteLine("这是我的测试方法,请在正式上线后注释掉");
        }
    }
}

此方法在2处调用

①:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AtrributeTest.com
{
    /// <summary>
    /// 用于测试Obsolete特性
    /// 目标:Method
    /// 消费者 : IDE
    /// </summary>
    public sealed class ObsoleteTest
    {
        [Obsolete("这个方法已经过时,请使用MyNewMethod方法",false)]
        public void MyOldMethd()
        {
            Console.WriteLine("这是一个过时的方法");
        }
        public void MyNewMethod()
        {
            Console.WriteLine("这是一个新方法");
            ConditionalTest contTest = new ConditionalTest();
            contTest.MyTestMethod();
        }
    }
}

②:Main函数

#define IsTest
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AtrributeTest.com;
namespace AtrributeTest
{
    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("ObsoleteTest..........................");
            ObsoleteTest obsTest = new ObsoleteTest();
            obsTest.MyNewMethod();

            Console.WriteLine("Program..........................");
            ConditionalTest conTest = new ConditionalTest();
            conTest.MyTestMethod();
            Console.ReadKey();
        }
    }
}

在Program中我定义了一个宏 IsTest , 所以在此类的Main函数中MyTestMethod是可以被执行的。但是在ObsoleteTest内中没有定义此宏,所以此类的方法MyNewMethod中的MyTestMethod是不会被执行的。这点值得注意。实际上在IDE中已经给予了提示:

在注册过IsTest宏的Program类,如下图:

技术分享

在没有注册过宏IsTest宏的ObsoleteTest类,如下图:

技术分享

值得注意注意的是 ,① 宏一定要放在所有using的前面 ; ②宏的定义要与[Conditional("IsTest")]后面的参数一样,但是不能要“”(引号)

但是如果整个项目的此Method都能/不能调用 , 单单一个个在Class中加/删宏会累死你的 。这里本人有个好方法“预处理指令”在本人的博客《C#的预处理指令的全局设计》中有,但是还有一个此特性还有一个缺点:

所有引用(调用)此Method的地方不会被编译,但是定义它的地方会被编译。建议还是使用#if / #endif


自定义特性:(要注意三点)

一:需要继承Attribute类

二:需要以Attribute单词作为后缀名

三:最好申明为sealed,需要申明此特性的消费着

好,现在来整一个Demo,现在一步步实现

①建立第一个自定义特性,如下图

技术分享

②完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AtrributeTest.com
{
    /// <summary>
    /// 自定义一个特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]//表示此特性可以应用到那些程序结构
    public  sealed class MyTestAttribute : Attribute
    {
        private string des;
        public int Id { get; set; }
        public MyTestAttribute(string @des)
        {
            this.des = des;
        }
    }
}

③使用自定义特性

注意 : 使用反射获取特性信息

技术分享

using System;
using AtrributeTest.com;
namespace AtrributeTest
{   
    [MyTest("我的第一个特性",Id = 1)]
    public class Program
    {
        private static void Main(string[] args)
        {
            Type @ty = typeof (Program);
            object[] arr = ty.GetCustomAttributes(false);//是否搜索父类上的特性
            MyTestAttribute my = arr[0] as MyTestAttribute;
            Console.WriteLine("特性类的des : {0}" , my.des);
            Console.WriteLine("特性类的ID号 : {0}" ,my.Id);
            Console.ReadKey();
        }
    }
}

本文出自 “Better_Power_Wisdom” 博客,请务必保留此出处http://aonaufly.blog.51cto.com/3554853/1912608

C#特性