C#高效編程話題集2(每期10話題)

 1:確保集合的線程安全 html

 

若是使用.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++)ide

{性能

     迭代this

}spa

第二類:

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("\ntemp2: ");
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);//2
     Console.WriteLine(MyList<string>.Count);//1
}
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表示定義一組條件並判斷參數是否符合條件;

 更多話題,期待下一期。

相關文章
相關標籤/搜索