天天看點

C#高效程式設計話題集2(每期10話題)

第一期話題在: C#高效程式設計話題集1(每期10話題) C#快速成長團隊 第二期話題來到。歡迎進入

進行讨論。

1:確定集合的線程安全

如果使用.net4.0,有新的線程安全集合類

新的 System.Collections.Concurrent 命名空間引入了多個新的線程安全集合類,可在需要時随時提供對項的無鎖通路,并在鎖适用時提供細粒度鎖定。 在多線程方案中使用這些類應獲得優于集合類型(例如, ArrayList 和 List <(Of <(T >)>))的性能。

除了System.Collections.Concurrent空間下集合外,非泛型集合使用

lock(非泛型集合對象.SyncRoot)進行鎖定達到集合線程安全目的

泛型集合使用

static object sycObj = new object(); //是否static看具體應用

lock (sycObj)

{

     //操作集合。

}

2:循環中先求長度還是使用list.Count,哪個效率高

第一類:

int len = list.Count; 

for(int i; i<len; i++)

{

     疊代

第二類:

for(int i; i<list.Count; i++)

答案是一樣高。

第一種方法完全沒有必要,很多人可能以為那樣會為代碼帶來效率,而實際上是不會給效率帶來任何提升。

因為事實上,索引器内部,為了安全期間,還是會去求整個list的count的。将兩者代碼貼出來可能會更好的了解這一點:

public T this[int index]

    get

    {

       if (index >= this._size)

      {

          ThrowHelper.ThrowArgumentOutOfRangeException();

      }

      return this._items[index];

    }

    set

        if (index >= this._size)

        {

            ThrowHelper.ThrowArgumentOutOfRangeException();

        }

        this._items[index] = value;

        this._version++;

}

public int Count

        return this._size;

3:善用延遲求值

以List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};為例,說明linq查詢中的延遲求值和主動求值。

List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var temp1 = from c in list where c > 5 select c;

var temp2 = (from c in list where c > 5 select c).ToList<int>();

list[0] = 11;

Console.Write("temp1: ");

foreach (var item in temp1)

    Console.Write(item.ToString() + " ");

Console.Write("\ntemp2: ");

foreach (var item in temp2)

4:謹慎泛型類型中的靜态成員

static void Main(string[] args)

     MyList<int> list1 = new MyList<int>();

     MyList<int> list2 = new MyList<int>();

     MyList<string> list3 = new MyList<string>();

     Console.WriteLine(MyList<int>.Count);

     Console.WriteLine(MyList<string>.Count);

class MyList<T>

     public static int Count { get; set; }

     public MyList()

     {

         Count++;

     }

代碼輸出是莫子?

隻要知道 MyList<int> 和 MyList<string> 是兩個不同的類型,這題就不難了解了。.NET 中類型參數不同的封閉泛型類型是不同的類型。

5:小心閉包中的陷阱

for (int i = 0; i < 10; i++)

     Action t = () =>

        Console.WriteLine("t1:" + i.ToString());

    };

    t.BeginInvoke(null, null);

以上代碼的輸出為?

當閉包中引用了外部的局部變量或者方法參數的時候,C#會把該變量編譯成一個類的執行個體字段,頂樓的代碼編譯後實際上等效于:

TempClass tp = new TempClass();

for (tp.i = 0; tp.i < 10; tp.i++)

  Action t = tp.TempMethod;

  t.BeginInvoke(null, null);

TempClass是C#編譯器自動生成的類,其定義大概是這樣:

class TempClass

  public int i;

  public void TempMethod()

  {

    Console.Writeline("t1:" + i.ToString());

  }

因為隻循環10次,幾乎一瞬間就完了,是以第一個異步委托還沒開始執行 tp.i 就等于10了

6:event關鍵字的作用

既然使用委托也能實作回調,為什麼又需要event關鍵字。答曰:event 最大的作用就是防止在類的外部觸發類的事件。

7:區分IEnumerable<T>和IQueryable<T>

本地資料源用IEnumerable<T>,遠端資料源用IQueryable<T>。

針對LinqLINQ TO to OBJECTS,使用Enumerable中的擴充方法對本地集合進行排序、查詢等操作,查詢參數接受的是Func< >。Func< >叫做謂語表達式,相當于一個委托。針對LinqLINQ TO to SQL則使用Querable中的擴充方法,它接受的參數是Expression< >。Expression< >用于包裝Func< >。LinqLINQ TO to SQL引擎最終會将表達式樹轉化成為相應的SQL語句,然後在資料庫中執行。

8:選擇正确的集合

檢視此文吧:

http://www.cnblogs.com/luminji/archive/2011/03/24/1993393.html

9:泛型參數的限制是不是應該叫約定更好

在泛型的使用過程中,常常使用到的一個功能就是為泛型參數設定限制。限制聽上去像是限制了泛型參數的使用範圍,而實際上,限制本身确實拓展了泛型參數的使用。

一個沒有限制的泛型參數,隻能具有object的行為和屬性,而一個指定限制為Student的泛型參數,卻可以使用類型Student的所有公開屬性和方法。

是以,俺覺得限制這個詞翻譯的實在不好,叫約定多好。

10:減少使用自定義委托

FCL中的3個(或者說3系列)委托已經滿足了大部分自定義委托的需求,是以基本上不再需要自定義委托了。

它們是:

Action表示接受0個或多個輸入參數,執行一段代碼,但是沒有任何傳回值;

Func表示接受0個或多個輸入參數,執行一段代碼,同時有傳回值;

Predicate表示定義一組條件并判斷參數是否符合條件;

 更多話題,期待下一期。

C#高效程式設計話題集3(每期10話題)

C#高效程式設計話題集2(每期10話題)

本文基于

Creative Commons Attribution 2.5 China Mainland License

釋出,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名

http://www.cnblogs.com/luminji

(包含連結)。如您有任何疑問或者授權方面的協商,請給我留言。