C#屬性

屬性是一個聲明性的標籤,用於向運行時傳遞有關程序中各種元素(如類,方法,結構,枚舉器,程序集等)的行爲的信息。可以通過使用屬性將聲明性信息添加到程序。聲明式標籤由放置在其所用元素上方的方括號([])表示。

屬性用於向程序添加元數據,如編譯器指令和其他信息,如註釋,描述,方法和類。*.Net*框架提供了兩種類型的屬性:預定義屬性和自定義構建的屬性。

指定屬性

用於指定屬性的語法如下:

[attribute(positional_parameters, name_parameter = value, ...)]
element

屬性名稱及其值在方括號內,在應用該屬性的元素之前指定。位置參數指定必要信息,名稱參數指定可選信息。

預定義屬性

.Net框架提供了三個預定義的屬性:

  • AttributeUsage
  • Conditional
  • Obsolete

預定義屬性:AttributeUsage

預定義屬性AttributeUsage描述瞭如何使用自定義屬性類。它指定可以應用該屬性的項目的類型。

用於指定此屬性的語法如下:

[AttributeUsage(
   validon,
   AllowMultiple=allowmultiple,
   Inherited=inherited
)]

其中,

  • 參數validon指定可以放置屬性的語言元素。它是枚舉器AttributeTargets的值的組合。默認值爲AttributeTargets.All
  • 參數allowmultiple(可選)爲此屬性的AllowMultiple屬性提供了一個布爾值。 如果些值爲:true,則表示屬性是多次使用。默認值爲false,表示一次性使用。
  • 參數inherited(可選)爲此屬性的Inherited屬性提供了一個布爾值。 如果此參數值爲:true,則屬性由派生類繼承。 它默認值爲false(不繼承)。

例如,

[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property, 
AllowMultiple = true)]

預定義屬性:Conditional

此預定義屬性標記一個條件方法,其執行取決於指定的預處理標識符。

它使方法調用條件編譯,具體取決於指定的值,如:調試(Debug)或跟蹤(Trace)。 例如,它在調試代碼時顯示變量的值。

用於指定此屬性的語法如下:

[Conditional(
   conditionalSymbol
)]

例如,

[Conditional("DEBUG")]

以下示例演示了該屬性:

#define DEBUG
using System;
using System.Diagnostics;

public class Myclass
{
   [Conditional("DEBUG")]
   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();
      Console.ReadKey();
   }
}

當上述代碼被編譯並執行時,它產生以下結果:

In Main function
In Function 1
In Function 2

預定義屬性: Obsolete

此預定義屬性標記不應該使用的程序實體。它能夠通知編譯器丟棄特定的目標元素。 例如,當一個類中正在使用一個新方法,並且如果仍然希望在類中保留舊方法時,可以通過顯示新方法而不是舊方法來顯示消息來將其標記爲過時。

用於指定此屬性的語法如下:

[Obsolete(
   message
)]
[Obsolete(
   message,
   iserror
)]

其中,

  • 參數 - message是一個字符串,描述項目過時的原因以及使用的替代方法。
  • 參數 - iserror,是一個布爾值。 如果值爲true,則編譯器應將該項目的使用視爲錯誤。默認值爲false,編譯器生成警告。

示例程序如下:

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

創建自定義屬性

.Net框架允許創建可用於存儲聲明性信息的自定義屬性,並可在運行時檢索。該信息可以根據設計標準和應用需要與任何目標元素相關。

創建和使用自定義屬性涉及四個步驟:

  • 聲明一個自定義屬性
  • 構造自定義屬性
  • 將自定義屬性應用於目標程序元素
  • 通過反射訪問屬性

最後一步是編寫一個簡單的程序來讀取元數據以找到各種標記。元數據是用於描述其他數據的數據或信息。程序可在運行時訪問屬性的反射。這將在下一章討論。

聲明自定義屬性

應該從System.Attribute類派生一個新的自定義屬性。 例如,

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

public class DeBugInfo : System.Attribute

在上面的代碼中,聲明瞭一個名稱爲DeBugInfo的自定義屬性。

構造自定義屬性

下面來構建一個名稱爲DeBugInfo的自定義屬性,它存儲通過調試任何程序獲得的信息。它存儲以下信息:

  • 錯誤代碼編號
  • 識別錯誤的開發人員的名稱
  • 代碼上次審查日期
  • 用於存儲開發人員言論的字符串消息

DeBugInfo類有三個私有屬性用於存儲前三個信息和一個用於存儲消息的公共屬性。 因此,錯誤編號,開發人員名稱和審查日期是DeBugInfo類的位置參數,並且消息是可選的或命名的參數。

每個屬性必須至少有一個構造函數。位置參數應通過構造函數傳遞。以下代碼顯示DeBugInfo類:

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

public class DeBugInfo : System.Attribute
{
   private int bugNo;
   private string developer;
   private string lastReview;
   public string message;

   public DeBugInfo(int bg, string dev, string d)
   {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
   }

   public int BugNo
   {
      get
      {
         return bugNo;
      }
   }

   public string Developer
   {
      get
      {
         return developer;
      }
   }

   public string LastReview
   {
      get
      {
         return lastReview;
      }
   }

   public string Message
   {
      get
      {
         return message;
      }
      set
      {
         message = value;
      }
   }
}

應用自定義屬性

該屬性是通過放置在目標之前來應用:

[DeBugInfo(45, "Maxsu", "12/8/2018", Message = "Return type mismatch")]
[DeBugInfo(49, "Sukyda", "10/10/2018", Message = "Unused variable")]
class Rectangle
{
   //member variables
   protected double length;
   protected double width;
   public Rectangle(double l, double w)
   {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Maxsu", "19/10/2018", Message = "Return type mismatch")]

   public double GetArea()
   {
      return length * width;
   }
   [DeBugInfo(56, "Maxsu", "19/10/2018")]

   public void Display()
   {
      Console.WriteLine("Length: {0}", length);
      Console.WriteLine("Width: {0}", width);
      Console.WriteLine("Area: {0}", GetArea());
   }
}

在下一章中,使用Reflection類對象檢索屬性信息。