1. 程式人生 > >大話C#語言——高階教程總結

大話C#語言——高階教程總結

推薦閱讀:

特性

       用於在執行時傳遞程式中各種元素(比如類、方法、結構、列舉、元件等)的行為資訊的宣告性標籤。

Net 框架提供了三種預定義特性:

AttributeUsage
Conditional
Obsolete

反射

       反射指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。
       程式集包含模組,而模組包含型別,型別又包含成員。反射則提供了封裝程式集、模組和型別的物件。

反射(Reflection)有下列用途:

它允許在執行時檢視特性(attribute)資訊。
它允許審查集合中的各種型別,以及例項化這些型別。
它允許延遲繫結的方法和屬性(property)。
它允許在執行時建立新型別,然後使用這些型別執行一些任務。

屬性

       使用 訪問器(accessors) 讓私有域的值可被讀寫或操作。例如:有一個名為 Student 的類,帶有 age私有域。我們不能在類的範圍以外直接訪問這些域,但是我們可以擁有訪問這些私有域的屬性。
程式碼實現如下:

using System;
namespace 屬性 { class Student { private int age = 0; // 宣告型別為 int 的 Age 屬性 public int Age { get { return age; } set { age = value; } } } class ExampleDemo { public
static void Main() { // 建立一個新的 Student 物件 Student s = new Student(); s.Age = 9; //9 // 增加年齡 s.Age += 1; //10 Console.ReadKey(); } } }

索引器

       允許一個物件可以像陣列一樣被索引。當為類定義一個索引器時,該類的行為就會像一個虛擬陣列(virtual array) 一樣。可以使用陣列訪問運算子 [ ] 來訪問該類的例項。
格式如下:

//索引器定義的時候帶有 this 關鍵字,它指向物件例項
element-type this[int index] 
{
   // get 訪問器
   get 
   {
      // 返回 index 指定的值
   }

   // set 訪問器
   set 
   {
      // 設定 index 指定的值 
   }
}

下面舉個例子來看看索引器如何使用:

using System;
namespace 索引器
{
   class IndexedNames
   {
      private string[] namelist = new string[size];
      static public int size = 10;
      //初始化每個元素的值
      public IndexedNames()
      {
         for (int i = 0; i < size; i++)
         namelist[i] = "N. A.";
      }
      public string this[int index]
      {
      //取值,輸出時用到
         get
         {
            string tmp;

            if( index >= 0 && index <= size-1 )
            {
               tmp = namelist[index];
            }
            else
            {
               tmp = "";
            }

            return ( tmp );
         }
         //設定值,重置值得時候使用
         set
         {
            if( index >= 0 && index <= size-1 )
            {
               namelist[index] = value;
            }
         }
      }

      static void Main(string[] args)
      {
         IndexedNames names = new IndexedNames();
         names[0] = "被重置後的值";
         for ( int i = 0; i < IndexedNames.size; i++ )
         {
            Console.WriteLine(names[i]);
         }
         Console.ReadKey();
      }
   }
}

上面程式碼在這裡就不做過多的解釋了,註釋已經在程式碼中標註。

委託

       C# 中的委託(Delegate)類似於 C 或 C++ 中函式的指標。委託(Delegate) 是存有對某個方法的引用的一種引用型別變數。派生自 System.Delegate 類。
格式:

[訪問修飾符] delegate <return type> <delegate-name> <parameter list>

例如:

public delegate int MyDelegate (string s);

使用方法:

using System;

delegate int NumberChanger(int n);
namespace 委託
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 建立委託例項
         NumberChanger nc1 = new NumberChanger(AddNum);
         // 使用委託物件呼叫方法
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

委託的多播:委託物件可使用 “+” 運算子進行合併。只有相同型別的委託可被合併。
例如:

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 建立委託例項
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         nc = nc1;         //15
         nc += nc2;        //15*5=75
         // 呼叫多播
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

下面再舉一個委託多播例項:例如小明叫小張買完車票,之後接著又讓他帶張電影票


// 小張類
public class MrZhang
    {
    // 其實買車票的悲情人物是小張
    public static void BuyTicket()
    {
            Console.WriteLine("NND,每次都讓我去買票,雞人呀!");
    }

    public static void BuyMovieTicket()
    {
        Console.WriteLine("我去,自己泡妞,還要讓我帶電影票!");
    }
}

//小明類
class MrMing
{
    // 宣告一個委託,其實就是個“命令”
    public delegate void BugTicketEventHandler();

    public static void Main(string[] args)
    {
        // 這裡就是具體闡述這個命令是幹什麼的,本例是MrZhang.BuyTicket“小張買車票”
        BugTicketEventHandler myDelegate = new BugTicketEventHandler(MrZhang.BuyTicket);

        myDelegate += MrZhang.BuyMovieTicket;
        // 這時候委託被附上了具體的方法
        myDelegate();
        Console.ReadKey();
    }
}

事件

       事件(Event) 基本上說是一個使用者操作,如按鍵、點選、滑鼠移動等等,或者是一些出現,如系統生成的通知。事件使用 釋出-訂閱(publisher-subscriber) 模型。包含事件的類用於釋出事件。這被稱為 釋出器(publisher) 類。其他接受該事件的類被稱為 訂閱器(subscriber) 類。
       釋出器(publisher) 是一個包含事件和委託定義的物件。事件和委託之間的聯絡也定義在這個物件中。釋出器(publisher)類的物件呼叫這個事件,並通知其他的物件。

       訂閱器(subscriber) 是一個接受事件並提供事件處理程式的物件。在釋出器(publisher)類中的委託呼叫訂閱器(subscriber)類中的方法(事件處理程式)。

       通過事件使用委託:在類的內部宣告事件,首先必須宣告該事件的委託型別。然後,宣告事件本身,使用 event 關鍵字。

例如:宣告一個myDelegate委託,然後宣告一個BoilerEventLog事件

//宣告委託
public delegate void myDelegate();

// 基於上面的委託定義事件
public event BoilerLogHandler BoilerEventLog;

例如:在名稱空間“通過事件使用委託”中,建立EventTest類作為釋出器,並宣告myDelegate委託和ChangeNum事件;建立subscribEvent類作為訂閱器類;建立MainClass類,註冊事件。


using System;
namespace 通過事件使用委託
{

  /***********釋出器類***********/
  public class EventTest
  {
    private int value;
	//委託
    public delegate void myDelegate();
	//事件
    public event myDelegate  ChangeNum;
    
    //建構函式
    public EventTest()
    {
      int n = 5;
      SetValue( n );
    }
    
    protected void OnNumChanged()
    {
      if ( ChangeNum != null )
      {
      	//有事件
        ChangeNum(); /* 事件被觸發 */
      }else {
      	//沒有事件
        Console.WriteLine( "event not fire" );
        Console.ReadKey(); /* 回車繼續 */
      }
    }
	//設定值,並觸發事件
    public void SetValue( int n )
    {
      if ( value != n )
      {
        value = n;
        OnNumChanged();
      }else{
	  Console.WriteLine( "值相等" );
      Console.ReadKey(); /* 回車繼續 */}
    }
  }


  /***********訂閱器類***********/

  public class subscribEvent
  {
    public void printf()
    {
      Console.WriteLine( "event fire" );
      Console.ReadKey(); /* 回車繼續 */
    }
  }

  /***********觸發***********/
  public class MainClass
  {
    public static void Main()
    {
      EventTest e = new EventTest(); /* 例項化物件,第一次沒有觸發事件(事件為空) */
      subscribEvent v = new subscribEvent(); /* 例項化訂閱器 */
      e.ChangeNum += new EventTest.myDelegate( v.printf ); /* 註冊事件 */
      e.SetValue( 7 );
      e.SetValue( 10 );
    }
  }
}

集合

       在 C# 中,集合繼承自System.Collection;在 C# 中,Object 類是所有資料型別的基類

1.動態陣列(ArrayList):可以替代一個數組。與陣列不同的是,可以使用索引在指定的位置新增和移除。

ArrayList al = new ArrayList();
al.Add(45);

2.雜湊表(Hashtable)儲存:鍵/值對,使用鍵來訪問集合中的元素。

Hashtable ht = new Hashtable();
ht.Add("001", "小木遊戲");

3.排序列表(SortedList):集合中的各項總是按鍵值排序排序,是陣列和雜湊表的組合,儲存鍵/值對,使用鍵和索引來訪問集合中的元素。如果使用索引訪問各項,則它是一個動態陣列(ArrayList),如果使用鍵訪問各項,則它是一個雜湊表(Hashtable)。

SortedList sl = new SortedList();
sl.Add("001", "小木遊戲");
sl.Add("001", "小木子");
Console.WriteLine( sl[0]);//小木遊戲

4.堆疊(Stack):後進先出

Stack st = new Stack();
st.Push('小木');
st.Push('遊戲');
st.Pop();//遊戲
st.Pop();//小木

5.佇列(Queue):先進先出

Queue q = new Queue();
q.Enqueue('小木');
q.Enqueue('遊戲');
char ch1 = (char)q.Dequeue();//小木
char ch2 = (char)q.Dequeue();//遊戲

6.點陣列(BitArray):使用布林值來表示,其中 true 表示位是開啟的(1),false 表示位是關閉的(0)。當需要儲存位,但是事先不知道位數時,則使用點陣列

// 建立兩1個大小為 8 的點陣列
BitArray ba1 = new BitArray(8);
 byte[] a = { 60 };
 for (int i = 0; i < ba1.Count; i++)
 {
      Console.Write("{0, -6} ", ba1[i]);//False False True True True True False False
 }

上面輸出結果為將60的二進位制數,轉換成對應的布林值。

泛型

       在封裝公共元件的時候,很多時候我們的類/方法不需要關注呼叫者傳遞的實體是"什麼",這個時候就可以使用泛型。
泛型方法:

//交換函式
 static void Swap<T>(ref T lhs, ref T rhs)
{
     T temp;
     temp = lhs;
     lhs = rhs;
     rhs = temp;
}

static void Main(string[] args)
{
     int a = 10;
     int b = 20;
     char c = 'I';
     char  d = 'V';
     // 呼叫 swap
     Swap<int>(ref a, ref b);
     Swap<char>(ref c, ref d);
     Console.ReadKey();
}

泛型委託:

delegate T NumberChanger<T>(T n);

 // 建立委託例項
NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);

匿名方法

匿名方法是通過使用 delegate 關鍵字建立委託例項來宣告的
例如:

delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x)
{
    Console.WriteLine("Anonymous Method: {0}", x);
};

下面舉個例子,使用兩種方法建立委託:


using System;

delegate void NumberChanger(int n);
namespace DelegateAppl
{
    class TestDelegate
    {
        static int num = 10;
        public static void AddNum(int p)
        {
            num += p;
            Console.WriteLine("Named Method: {0}", num);
        }

        static void Main(string[] args)
        {
			///////////////方法一
            // 使用匿名方法建立委託例項
            NumberChanger nc = delegate(int x)
            {
               Console.WriteLine("Anonymous Method: {0}", x);
            };
            // 使用匿名方法呼叫委託
            nc(10);
			
			//////////////方法二
            // 使用命名方法例項化委託
            nc =  new NumberChanger(AddNum);
            // 使用命名方法呼叫委託
            nc(5);
            Console.ReadKey();
        }
    }
}

不安全程式碼

       不安全程式碼或非託管程式碼是指使用了指標變數的程式碼塊。當一個程式碼塊使用 unsafe 修飾符標記時,C# 允許在函式中使用指標變數
例如:在函式返回型別前加上關鍵字unsafe ,函式中便可以使用指標。

public unsafe void swap(int* p, int *q)
{
    int temp = *p;
    *p = *q;
    *q = temp;
}

多執行緒

       執行緒是輕量級程序。一個使用執行緒的常見例項是現代作業系統中並行程式設計的實現。為了同時執行多個任務,它可以被劃分為更小的執行緒。
       執行緒生命週期開始於 System.Threading.Thread 類的物件被建立時,結束於執行緒被終止或完成執行時。

執行緒生命週期中的各種狀態:

1.未啟動狀態:當執行緒例項被建立但 Start 方法未被呼叫時的狀況。
2.就緒狀態:當執行緒準備好執行並等待 CPU 週期時的狀況。
3.不可執行狀態:下面的幾種情況下執行緒是不可執行的:
已經呼叫 Sleep 方法
已經呼叫 Wait 方法
通過 I/O 操作阻塞
4.死亡狀態:當執行緒已完成執行或已中止時的狀況。

       程序中第一個被執行的執行緒稱為主執行緒。當 C# 程式開始執行時,主執行緒自動建立。使用 Thread 類的 CurrentThread 屬性訪問執行緒。
1.建立執行緒用Thread :

Thread childThread = new Thread(“主執行緒名”);

注意:這種方法是建立子執行緒,因為主執行緒在程式開始時自動被建立
2.暫停執行緒用 sleep() 方法:

Thread.Sleep(暫停時間);

3.銷燬執行緒用Abort()方法:

執行緒名.Abort();