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
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM