【C#】C#進階筆記

接下來是C#的進階教程了,仍然是雜七雜八並不全面的隨筆。

1. 特性(Attribute)

特性(Attribute)是用於在運行時傳遞程序中各種元素(比如類、方法、結構、枚舉、組件等)的行爲信息的聲明性標籤。您可以通過使用特性向程序添加聲明性信息。
特性(Attribute)用於添加元數據,如編譯器指令和註釋、描述、方法、類等其他信息。

1.1 預定義特性

1.1.1 AttributeUsage

描述瞭如何使用一個自定義特性類。它規定了特性可應用到的項目的類型。語法如下:

[AttributeUsage(
	// 規定特性可被放置的語言元素。它是枚舉器 AttributeTargets 的值的組合。默認值是 AttributeTargets.All。
   validon,
   // allowmultiple(可選的)爲該特性的 AllowMultiple 屬性(property)提供一個布爾值。如果爲 true,則該特性是多用的。默認值是 false(單用的)。
   AllowMultiple=allowmultiple,
   //inherited(可選的)爲該特性的 Inherited 屬性(property)提供一個布爾值。如果爲 true,則該特性可被派生類繼承。默認值是 false(不被繼承)。
   Inherited=inherited
)]
1.1.2 Conditional

這個暫時不瞭解,等後面如果實際需要的時候再補上。。。

1.1.3 Obsolete

標記了不應被使用的程序實體。它可以讓您通知編譯器丟棄某個特定的目標元素。例如,當一個新方法被用在一個類中,但是您仍然想要保持類中的舊方法,您可以通過顯示一個應該使用新方法,而不是舊方法的消息,來把它標記爲 obsolete(過時的)。例如:

class Program
    {
        /*
         * 參數 message,是一個字符串,描述項目爲什麼過時的原因以及該替代使用什麼。
         * 參數 iserror,是一個布爾值。如果該值爲 true,編譯器應把該項目的使用當作一個錯誤。默認值是 false(編譯器生成一個警告)。
         */
        [Obsolete("不要用舊方法啦",true)]
        static void OldMethod() {
            Console.WriteLine("這是一箇舊方法");
        }
        static void NewMethod() {
            Console.WriteLine("這是新的方法");
        }
        static void Main(string[] args)
        {
            OldMethod();
            Console.ReadKey();
        }
    }

因爲iserror屬性設置爲了true,所以在main方法調用OldMethod方法時報錯,
在這裏插入圖片描述

1.2 自定義特性

1、創建一個自定義特性:

// 描述如何使用一個自定義特性 SomethingAttribute
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]    

//********自定義特性SomethingAttribute**************//
public class SomethingAttribute : Attribute    {
    private string name; // 名字
    private string data; // 日期
    public string Name {
        get { return name; }
        set { name = value; }
    }
    public string Data    {
        get { return data; }
        set { data = value; }
    }
    public SomethingAttribute(string name)    {
        this.name = name;
        this.name = name;
    }
}

2、實例化自定義

[Something("Amy", Data = "2018-06-18")]
[Something("Jack", Data = "2018-06-18")]
class Test{}

3、獲取自定義特性的中的變量

Type t = typeof(Test);
var something = t.GetCustomAttributes(typeof(SomethingAttribute),true);
foreach(SomethingAttribute each in something)
{
    Console.WriteLine("Name:{0}", each.Name);
    Console.WriteLine("Data:{0}",each.Data);
}

2.反射(Reflection)

反射指程序可以訪問、檢測和修改它本身狀態或行爲的一種能力。

2.1 優缺點

優點:

  • 1、反射提高了程序的靈活性和擴展性。
  • 2、降低耦合性,提高自適應能力。
  • 3、它允許程序創建和控制任何類的對象,無需提前硬編碼目標類。

缺點:

  • 1、性能問題:使用反射基本上是一種解釋操作,用於字段和方法接入時要遠慢於直接代碼。因此反射機制主要應用在對靈活性和拓展性要求很高的系統框架上,普通程序不建議使用。
  • 2、使用反射會模糊程序內部邏輯;程序員希望在源代碼中看到程序的邏輯,反射卻繞過了源代碼的技術,因而會帶來維護的問題,反射代碼比相應的直接代碼更復雜。

2.2 反射的用途

  • 它允許在運行時查看特性(attribute)信息。
  • 它允許審查集合中的各種類型,以及實例化這些類型。
  • 它允許延遲綁定的方法和屬性(property)。
  • 它允許在運行時創建新類型,然後使用這些類型執行一些任務。

2.3 使用反射來查看特性(attribute)信息

獲取類和方法特性。
例如:

using System;
using System.Reflection;
namespace BugFixApplication
{
   // 一個自定義特性 BugFix 被賦給類及其成員
   [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, "Zara Ali", "12/8/2012",
    Message = "Return type mismatch")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012",
    Message = "Unused variable")]
   class Rectangle
   {
      // 成員變量
      protected double length;
      protected double width;
      public Rectangle(double l, double w)
      {
         length = l;
         width = w;
      }
      [DeBugInfo(55, "Zara Ali", "19/10/2012",
       Message = "Return type mismatch")]
      public double GetArea()
      {
         return length * width;
      }
      [DeBugInfo(56, "Zara Ali", "19/10/2012")]
      public void Display()
      {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle  
   
   class ExecuteRectangle
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Display();
         Type type = typeof(Rectangle);
         // 遍歷 Rectangle 類的特性
         foreach (Object attributes in type.GetCustomAttributes(false))
         {
            DeBugInfo dbi = (DeBugInfo)attributes;
            if (null != dbi)
            {
               Console.WriteLine("Bug no: {0}", dbi.BugNo);
               Console.WriteLine("Developer: {0}", dbi.Developer);
               Console.WriteLine("Last Reviewed: {0}",
                    dbi.LastReview);
               Console.WriteLine("Remarks: {0}", dbi.Message);
            }
         }
         
         // 遍歷方法特性
         foreach (MethodInfo m in type.GetMethods())
         {
            foreach (Attribute a in m.GetCustomAttributes(true))
            {
               DeBugInfo dbi = (DeBugInfo)a;
               if (null != dbi)
               {
                  Console.WriteLine("Bug no: {0}, for Method: {1}",
                        dbi.BugNo, m.Name);
                  Console.WriteLine("Developer: {0}", dbi.Developer);
                  Console.WriteLine("Last Reviewed: {0}",
                        dbi.LastReview);
                  Console.WriteLine("Remarks: {0}", dbi.Message);
               }
            }
         }
         Console.ReadLine();
      }
   }
}

運行結果會顯示附加到類 和方法上的自定義特性:

Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: 

3. 屬性(Property)

屬性(Property) 是類(class)、結構(structure)和接口(interface)的命名(named)成員。類或結構中的成員變量或方法稱爲 域(Field)。屬性(Property)是域(Field)的擴展,且可使用相同的語法來訪問。它們使用 訪問器(accessors) 讓私有域的值可被讀寫或操作。
看起來很複雜,其實從下面這個例子就可以直觀地瞭解到什麼是屬性啦:

// 聲明類型爲 string 的 Code 屬性
public string Code
{
   get
   {
      return code;
   }
   set
   {
      code = value;
   }
}

在上面一個例子中,Code就是一個屬性,get 、 set就是訪問器。

3.1 抽象屬性

抽象類可擁有抽象屬性,這些屬性應在派生類中被實現。

public abstract class Person
   {
      public abstract string Name
      {
         get;
         set;
      }
      public abstract int Age
      {
         get;
         set;
      }
   }

在派生類中:

class Student : Person
   {
      private string name = "N.A";
      private int age = 0;

      // 聲明類型爲 string 的 Name 屬性
      public override string Name
      {
         get
         {
            return name;
         }
         set
         {
            name = value;
         }
      }

      // 聲明類型爲 int 的 Age 屬性
      public override int Age
      {
         get
         {
            return age;
         }
         set
         {
            age = value;
         }
      }
      public override string ToString()
      {
         return "Name = " + Name + ", Age = " + Age;
      }
   }

4. 索引器(Indexer)

索引器(Indexer) 允許一個對象可以像數組一樣被索引。當您爲類定義一個索引器時,該類的行爲就會像一個 虛擬數組(virtual array) 一樣。您可以使用數組訪問運算符([ ])來訪問該類的實例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章