zoukankan      html  css  js  c++  java
  • C#语法之特性

    在项目中经常可以看到在类属性上面有一个[]的东西,今天讲的东西就是它,它英文名是Attribute,中文名是特性。

    一、什么是特性?

    首先,我们肯定Attribute是一个类,下面是msdn文档对它的描述:
    公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。

    在.NET中,Attribute被用来处理多种问题,比如序列化、程序的安全特征、防止即时编译器对程序代码进行优化从而代码容易调试等等。下面,我们先来看几个在.NET中标准的属性的使用,稍后我们再回过头来讨论Attribute这个类本身。(文中的代码使用C#编写,但同样适用所有基于.NET的所有语言)。上面的解释说实话这是我复制粘贴的。

    二、自定义特性

    除了C#中系统自带的特性外我们可以自己定义一些特性。所有自定义的Attribute必须从Attribute类派生,命名也是要以Attribute结尾,在使用的时候可以省略Attribute。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    
    namespace CusAttribute
    {
        [AttributeUsage(AttributeTargets.Class,AllowMultiple =true,Inherited =false)]
        public class CustomAttribute:System.Attribute
        {
            public string CustormDescription { get; }
    
            public CustomAttribute(string des)
            {
                CustormDescription = des;
            }
        }
    }

    在上面的代码中定义了一个CustomAttribute特性,继承自Attribute类,主要功能是为类添加描述信息。不过在类声明的上一行有一个中括号[AttributeUsage(AttributeTargets.Class,AllowMultiple =true,Inherited =false)] ,这里面的AttributeUsage又是什么玩意呢?我们可以转到定义来看一下:

    看定义可以看到,AttributeUsage其实也是继承自Attribute,也是一个特性。那来说下这个类里面的3个属性validOn、AllowMultiple、Inherited.

    1.validOn:可以看到它是AttributeTargets类型,而AttributeTargets转到定义可以看到是一个枚举类型。指明Attribute 可以被施加的元素的类型。

    2.AllowMultiple:它是一个布尔值。表示是否可以对一个程序元素施加多个Attribute。

    3.Inherited:它也是一个布尔值,表示是否施加的Attribute 可以被派生类继承或者重载

    使用下面的代码一步一步验证上面的3个属性。

    我们定义了一个Person基类,定义了Student类继承自Person类。

    1.AllowMultiple

    将上面的特性设置为[AttributeUsage(AttributeTargets.Class,AllowMultiple =true,Inherited =false)]时

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    
    namespace CusAttribute
    {
        [CustomAttribute("")]
        [Custom("基类")]
        public class Person
        {
            
            public string Name { get; set; }
    
            public int Age { get; set; }
        }
    }

    上面使用两次特性,也是没有报错是可以的,但是如果AllowMultiple设为false,编译时就会报错.

    2.Inherited

    先把Student、Person类也贴出来

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CusAttribute
    {
        [CustomAttribute("学生")]
        public class Student:Person
        {
            public string StudentId { get; set; }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    
    namespace CusAttribute
    {
        //[CustomAttribute("人")]
        [Custom("基类")]
        public class Person
        {
            
            public string Name { get; set; }
    
            public int Age { get; set; }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    
    
    namespace CusAttribute
    {
        class Program
        {
            static void Main(string[] args)
            {
                
                System.Reflection.MemberInfo info = typeof(Student);
                object[] attributes = info.GetCustomAttributes(true);
                for (int i = 0; i < attributes.Length; i++){
                    CustomAttribute attr = (CustomAttribute)attributes[i];
                    System.Console.WriteLine("{0} {1}", attr.CustormDescription, attributes[i]);
                }
    
                Console.WriteLine("-----------------------");
                 info = typeof(Person);
                attributes = info.GetCustomAttributes(true);
                for (int i = 0; i < attributes.Length; i++)
                {
                    CustomAttribute attr = (CustomAttribute)attributes[i];
                    System.Console.WriteLine("{0} {1}",attr.CustormDescription,attributes[i]);
                }
                Console.ReadLine();
            }
        }
    }

    在main方法中我们Student和Person类中的特性并输出,通过反射,至于反射以后会有提到

    和AllowMultiple一起有4种可能性.

    AllowMultiple:false      Inherited:true

    AllowMultiple:false      Inherited:false

    AllowMultiple:true  Inherited:false

    AllowMultiple:true  Inherited:true

    对于Inherited:false时就不说了,不能被派生类继承,当Inherited:true时,AllowMultiple:true的话派生类不会覆盖父类的特性,AllowMultiple:false的话派生类会覆盖父类的特性。

    3.validOn

    这个主要是一个枚举。可以看下枚举都有什么.也就是说可以将特性应用到下面的枚举类型中。

      //
        // 摘要:
        //     指定可以对它们应用特性的应用程序元素。
        [ComVisible(true)]
        [Flags]
        public enum AttributeTargets
        {
            //
            // 摘要:
            //     可以对程序集应用属性。
            Assembly = 1,
            //
            // 摘要:
            //     可以对模块应用属性。
            Module = 2,
            //
            // 摘要:
            //     可以对类应用属性。
            Class = 4,
            //
            // 摘要:
            //     可以对结构应用属性,即值类型。
            Struct = 8,
            //
            // 摘要:
            //     可以对枚举应用属性。
            Enum = 16,
            //
            // 摘要:
            //     可以对构造函数应用属性。
            Constructor = 32,
            //
            // 摘要:
            //     可以对方法应用属性。
            Method = 64,
            //
            // 摘要:
            //     可以对属性 (Property) 应用属性 (Attribute)。
            Property = 128,
            //
            // 摘要:
            //     可以对字段应用属性。
            Field = 256,
            //
            // 摘要:
            //     可以对事件应用属性。
            Event = 512,
            //
            // 摘要:
            //     可以对接口应用属性。
            Interface = 1024,
            //
            // 摘要:
            //     可以对参数应用属性。
            Parameter = 2048,
            //
            // 摘要:
            //     可以对委托应用属性。
            Delegate = 4096,
            //
            // 摘要:
            //     可以对返回值应用属性。
            ReturnValue = 8192,
            //
            // 摘要:
            //     可以对泛型参数应用属性。
            GenericParameter = 16384,
            //
            // 摘要:
            //     可以对任何应用程序元素应用属性。
            All = 32767
        }
  • 相关阅读:
    hadoop3.2.0集群搭建的一些坑!
    springboot整合elasticJob实战(纯代码开发三种任务类型用法)以及分片系统,事件追踪详解
    Flask接口返回JSON格式数据自动解析
    Struts2--国际化
    Struts2--标签tag
    Struts2-OGNL
    Struts2--拦截器Interceptor
    Struts2--struts.xml详解
    Spring--事务管理
    Spring--JDBC
  • 原文地址:https://www.cnblogs.com/5ishare/p/5768464.html
Copyright © 2011-2022 走看看