C# 特性

本文介绍了C#中特性的作用、定义和用法。特性可影响编译和运行,它直接或间接继承于attribute,约定以Attribute结尾。还介绍了自定义特性,以及AttributeUsage特性的参数作用。通过反编译工具和反射获取特性,指出特性需依赖第三方使用,且在编译时确定。

特性有什么用?

 

     [Obsolete("请不要使用这个类!")]
    public  class Child: Parent
    {
    }

在类上面使用 特性,然后重新编译就会有如下输出

  

如果使用 obsolete 的重载方法 

由此

特性可以影响编译

 

 

再者:

   [Serializable]
    public  class Child: Parent
    {}

表示该类可以序列化

 

特性可以影响运行

 

 

特性是什么?

Attribute:

特性就是直接或者间接继承 于 attribute

约定俗称  特性 都以 Attribute 结尾,在书写的时候就像 MVC 的控制器省略 Collector 一样省略 Attribute

自己写一个特性:

//[AttributeUsage(AttributeTargets.All,AllowMultiple =true)]
    class CustomAttribute:Attribute
    {
       public CustomAttribute()
       {

       }

        public CustomAttribute(int num)
        {

        }

        public CustomAttribute(string str)
        {

        }
    }

使用: 发现给一个类添加多个特性会报错

需要取消代码上的 注释,就可以添加多个重复特性

AttributeUsage 特性是用于特性的特性 ,

第一个参数决定了可以用于什么类型的对象 例如 class 类 ,delegate 委托,Method 方法等

第二个参数决定能否重复修饰

第三个参数 决定 子类中该特性是否生效

 [AttributeUsage(AttributeTargets.All,AllowMultiple =true,Inherited =true)]

特性的用法:


        [Custom("字符串")]
        [Custom(Remark ="随便")]
        [Custom(Remark = "随便",Decision ="特性的字段可以这样赋值")]
        [return:Custom, Custom(Remark = "返回值也可以重复修饰", Decision = "特性的字段可以这样赋值")]//修饰返回值
        public  string CommonSay([Custom, Custom(Remark = "参数也可以重复修饰", Decision = "参数也可以重复修饰")] string   str)//修饰参数
        {
            Console.WriteLine("子级的普通方法"+str);
            return str;
        }

通过反编译工具会发现在IL语言中  特性会 进入到标记的目标内部

这个.custom 我们无法在C#中访问到 ,我们自己写的特性似乎没任何用处

 

 [Serializable]   [Obsolete]   是系统自带的特性,   把他们带上反编译会产生什么呢?

用反射来获取特性:

public  class InvokeCenter
    {
        public static void ManagerStudent<T>(T user) where T : Child
        {
            Console.WriteLine( $"{user.Id}_{user.Name}");
            user.Study();
            user.Answer();

            var type = user.GetType();

            //用反射获取类上的Custom 特性
            if (type.IsDefined(typeof(CustomAttribute),true))
            {
                object[] oAttributeArray = type.GetCustomAttributes(typeof(CustomAttribute),true);
                foreach (CustomAttribute attr in oAttributeArray)
                {
                    attr.Show();
                }
            }

            //用反射获取属性上的Custom 特性
            foreach (var prop in type.GetProperties())
            {
                if (prop.IsDefined(typeof(CustomAttribute), true))
                {
                    object[] attr = prop.GetCustomAttributes(typeof(CustomAttribute), true);
                    foreach (CustomAttribute item in attr)
                    {
                        item.Show();
                    }
                }
            }

            
            //用反射获取属性上的Custom 特性
            foreach (var method in type.GetMethods())
            {
                if (method.IsDefined(typeof(CustomAttribute), true))
                {
                    object[] attr = method.GetCustomAttributes(typeof(CustomAttribute), true);
                    foreach (CustomAttribute item in attr)
                    {
                        item.Show();
                    }
                }
            }
           

        }

    }

特性代码:


    [AttributeUsage(AttributeTargets.All,AllowMultiple =true,Inherited =true)]
    class CustomAttribute:Attribute
    {
       public CustomAttribute()
       {
            Console.WriteLine($"{this.GetType().Name}的无参构造函数");
       }

        public CustomAttribute(int num)
        {
            Console.WriteLine($"{this.GetType().Name}的int构造函数");
            this.Id = num;
        }

        public CustomAttribute(string str)
        {
            Console.WriteLine($"{this.GetType().Name}的string构造函数");
            this.Name = str;
        }

        public int Id { get; set; }

        public string Name { get; set; }

        public string Remark { get; set; }

        public string Decision { get; set; }

        public void Show()
        {
            Console.WriteLine($"Id:{this.Id},Name:{this.Name},Remark:{this.Remark},Decision:{this.Decision}");
        }

    }

使用特性的类


    [Custom]
    [Custom(123)]
    [Custom("456")]
    [Custom("456",Remark ="哈哈哈哈")]
    [Custom("456", Remark = "哈哈哈哈",Decision ="你好!")]
    public abstract class Parent
    {

        private void PrivSaySomeWord()
        {
            Console.WriteLine("我是一个私有方法!");
        }

        private string PrivProp { get; set; }

    }
   
    [Serializable]
    [Obsolete]
    [Custom]
    public  class Child: Parent
    {
        [Custom]
        public int Id { get; set; }
        [Custom]
        public string Name { get; set; }

        [Custom]
        public void Study()
        {
            Console.WriteLine("我在学习!");

        }
       
        public void Answer()
        {
            Console.WriteLine("我在回答!");

        }
       
        [Custom("字符串")]
        [Custom(Remark ="随便")]
        [Custom(Remark = "随便",Decision ="特性的字段可以这样赋值")]
        [return:Custom, Custom(Remark = "返回值也可以重复修饰", Decision = "特性的字段可以这样赋值")]//修饰返回值
        public  string CommonSay([Custom, Custom(Remark = "参数也可以重复修饰", Decision = "参数也可以重复修饰")] string   str)//修饰参数
        {
            Console.WriteLine("子级的普通方法"+str);
            return str;
        }
    }

调用:

  var child = new Child();
            InvokeCenter.ManagerStudent(child);
            Console.ReadLine();

结果:

 

如上特性本身是没有用的,需要依赖 第三方 例如 上面的类 InvokeCenter 类  去主动检测和使用

特性 是在编译时确定的   :有 string 类型的构造函数 ,但是使用 类的 属性 会报错 ,因为 特性早在编译时确定,不能用变量

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值