程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#高效編程話題集2

C#高效編程話題集2

編輯: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
{
    get
    {
        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(" temp2: ");
foreach (var item in temp2)
{
    Console.Write(item.ToString() + " ");
}

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:選擇正確的集合

查看此文吧:html">http://www.BkJia.com/kf/201104/88261.html

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

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

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

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

10:減少使用自定義委托

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

它們是:

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

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

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

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved