成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

解析C# CLR的15個細節

開發 后端
本文整理了關于C# CLR的15個知識點。這些都是最為基本的知識,但由于現在大家對CLR還不是很了解,所以看起來會有一絲不理解,還是希望能給大家帶來幫助。

本文整理了關于C# CLR的15個知識點。這些都是最為基本的知識,但由于現在大家對CLR還不是很了解,所以看起來會有一絲不理解,還是希望能給大家帶來幫助。

1、C# CLR之foreach的性能問題

foreach(string s in rows) { foo(s); }的實現是:

  1. IEnumerator e = rows.GetEnumerator();  
  2. try {  
  3.   string s;  
  4.   while (e.MoveNext()) {  
  5.     s = (String) e.Current;  
  6.     foo(s);  
  7.   }  
  8. }  
  9. finally {  
  10.   IDisposable d = e as IDisposable;  
  11.   if (d != null) d.Dispose();  

每一步都調用了e.MoveNext()和e.Current兩個方法;而大多數時候,完全有可能優化為一次調用。顯然這對性能是有影響的。雖然foreach對于數組作了單獨的優化(編譯成for循環),但這還是值得注意的。

那么,怎么做比較快?

對于List等Collection,可以用ForEach(Action action),FindAll(Predicate match),ConvertAll(Converter converter)等方法。它們比較快,但不是所有實現IEnumerable的類都提供。

LINQ追求compatiblity,而不是performance。因此LINQ的實現完全采用了foreach。值得注意。

2、C# CLR之yield的實現原理

實現一個支持IEnumerable的對象時,一般會用到yield關鍵字,這樣foreach遍歷這個對象時,可以做到lazy evaluation。例如:

  1. class MyCollection: IEnumerable<char> 
  2. {  
  3.   private string s; ...  
  4.   public IEnumerable<char> GetEnumerator()
  5.  {  
  6.     for (int i=0; i<s.Length; i++)
  7.   {  
  8.       yield return s[i];  
  9.     }  
  10.  }  

執行到yield時函數返回,下次調用時,接著上次運行的位置繼續運行。這個continuation的效果是怎么做的呢?

包含yield的函數都會被編譯器做成一個狀態機。每調一次,就接著上次的狀態繼續運行。簡單有效啊。我一直以為要有什么特殊的辦法呢。

3、C# CLR之exception handling的實現決定了throw的performance較差。

可以用Int32.TryParse代替try{Int32.Parse…}catch{…},稍快一點。類似地建議使用Dictionary.TryGetValue。

4、C# CLR之.Net CLR執行引擎對應于MSCorWks.dll和MSCorEE.dll這兩個文件。

5、C# CLR之.Net 3.0, 3.5沒有對CLR作任何修改。

所有增加的東西(比如LINQ)都是syntactic sugar,只改了C#編譯器而已。

6、C# CLR之AppDomain

如果把.Net虛擬機看成一個虛擬操作系統,AppDomain的概念則類似于操作系統中的進程。

可以用代碼創建一個AppDomain,然后動態加載/卸載assembly,還可以設置權限,相當于提供了一個沙箱。

跨AppDomain的調用類似于RPC。

調用某個AppDomain內部的obj.foo(x)時,.net會自動幫你做出一個proxy object,你所調用的obj其實是一個proxy object。傳給foo的參數x會先被被marshal,以保證AppDomain被安全隔離。

誰用AppDomain?SQL Server用這個技術實現managed存儲過程。IIS會把不同的Web Application放在不同的AppDomain里,以實現動態裝卸。

7、C# CLR之動態載入Assembly的陷阱

Sytem.Reflection.Assembly.LoadFrom(pathName)并不會載入pathName所指定的dll,而是看看pathName那個dll的名字、版本,然后到系統默認位置去找。(陷阱啊)

8、C# CLR之C#里用reflection創建一個新對象

用Activator.CreateInstance。(奇怪的名字啊。)

9、C# CLR之C#泛型之“where”

可以用“where”來限定T的接口。例如

static T min(T arg1, T arg2) where T: IComparable {…}

不寫where的話,就不能調arg1.CompareTo(arg2)。

為啥不把T換成IComparable?一是為保證arg1, arg2一定是同一個類型,二是泛型的效率更高。(JIT會為不同類型的T各生成一份native code,從而避免了boxing)

更多where的細節:

* 要想調T t1 = new T(),必須聲明where T: new()或者where T: struct

* 要寫T t2 = null,必須聲明where T: class

* T z = default(T)是一個特殊的用法,會把T的每個bit都置為0。

* 假設定義了Foo(T x, T y),則if (x==null) … 是可以通過的,雖然C#中value type的值不允許為null(例如int a=null是錯的)。這是因為,此時的語義是一致的,反正if里面的操作不被執行就是了,所以編譯器對這種特殊情況網開一面。

* if (x==y)不行,除非寫了where T: baseclass。(這里我也沒理解為啥。。。>_<好像說是不知道應該用reference比較還是value比較?)

10、C# CLR之匿名函數的背后。。。

在C# 2.0以后可以用匿名的delegate,如ThreadPool.QueueWorkItem(delegate (Object obj) { Console.WriteLine(obj); })

但編譯器的實現會帶來一點點overhead,會生成一個小小的靜態WaitCallback對象,可以用Reflector看生成的代碼。(不要打開Reflector的optimization,否則就看不到了)

如果是自己寫的話,可以選擇每次動態建立一個WaitCallback對象然后銷毀。當然這樣做性能可能差一些,但這里的idea是:編譯器會自動做一些事,但不一定是你所希望的。在使用這些高級feature前,最好先搞清楚背后發生了什么。

另一個細節:如果匿名函數中使用了外層函數的局部變量(即所謂的function closure),會導致創建額外的shared-state object,把用到的局部變量做成一個新對象傳給匿名函數。

上述描述同樣適用于lambda函數。因為C#的lambda函數就是匿名函數,改了改語法而已。

11、C# CLR之Nullable type

雖然C#要求value type的值不能是null,但寫數據庫程序時經常遇到某個值是null的情況。為此,C#2.0引入了Nullable type。例如,int? x = null。

int? x其實就是一個縮寫,等價于Nullable x。Nullable是預定義的一個類,簡單地對x作了封裝。(因為增加了一個類,顯然對性能稍微有點影響)

這個小改動的實現其實很麻煩,需要修改CLR。為什么?因為原先的x是一個value type,現在則變成了一個object,看這個:

  1. void M(Object o)   
  2. {  
  3.   if (o=null) {Bar();}  
  4. }  
  5. void F()  
  6. {  
  7.   int? x = null;  
  8.   M(x);  
  9. }  
  10.  

如果CLR不專門做修正的話,上面的Bar()不會被執行。(思考題:想一想為什么~)

另外,C#還引入了一個默認值運算符“??”,稱為null-coalescing operator。

一句話,x ?? value是 (x==null) ? value: x的簡寫。

12、C# CLR之屬性(property)的簡單聲明

  1. public int x {get; private set;} 

是個很好用的句式。

注意,

  1. public int x {get;} 

是錯誤的,不能通過編譯。

13、C# CLR之Extension method

  1. //Extension method  
  2. static class MyExtMethods   
  3. {  
  4.   static public GetFirstLetter(this string s) {return s[0];}  
  5. }  
  6.  

然后就可以用string s = “hello”; char ch = s.GetFirstLetter()了。

原理很簡單,編譯器把上面那句話翻譯成MyExtMethods.GetFirstLetter(s)。LINQ就用到了這個技術。

14、C# CLR之匿名類型的背后。。。

  1. var o = new {name = “Xiangpeng”, id = 123 }; 

在這背后是編譯器生成的一個匿名類,包含了兩個只讀屬性,形如public int id { get {return _id;} }為什么不做成可讀寫的呢?

很微妙。匿名類自動生成了GetHashCode(),返回的是對所有屬性的hash code做XOR的結果。如果允許修改屬性值,那么Hash code的值就會變化;而這個可能會出問題~保險起見,只讀吧。

15、C# CLR之每個thread占1M物理內存

在Win32編程中thread的1M stack空間是Reserve的,直到真正用時才占用物理內存;而在.net中,這1M空間直接被commit。

還好,可以在新建thread時指定stack size。不過這也比較危險,設小了怕不夠。實際上,最好盡量避免創建thread——太多的thread要么導致CPU競爭和context switch,要么都block著浪費內存。建議是:能用ThreadPool就用ThreadPool。

以上就是對C# CLR的比較介紹。

【編輯推薦】

  1. 淺析基于SQL2005的CLR存儲過程
  2. 分析與對比CLR Via C#靜態構造函數的性能
  3. 為你解疑:CLR是什么?
  4. linq to sql多表查詢淺析
  5. linq to sql多表基礎描述
責任編輯:阡陌 來源: 博客
相關推薦

2009-09-18 09:59:39

C# CLR

2009-09-18 09:02:45

CLR Via C#

2024-06-24 03:00:00

2024-03-20 10:59:37

開源

2009-09-14 18:34:32

C# List排序

2009-09-17 18:56:22

CLR Via C#

2009-10-23 11:31:05

CLR Via C#調

2011-06-22 10:04:03

C#開發

2009-10-22 19:11:25

CLR Via C#教

2009-09-09 14:40:15

C# XML解析

2009-08-31 17:47:43

C#接口使用

2009-08-31 18:01:41

C#接口事件

2009-09-02 16:30:20

C#定義數組

2009-08-31 17:16:12

C#實現接口

2009-08-27 17:40:21

C#接口的作用

2009-08-31 17:30:10

C#接口的作用

2009-09-02 16:41:56

C#聲明數組

2009-09-07 15:27:04

C# MessageB

2009-09-17 16:41:12

C#組件編程

2009-08-18 10:47:40

C#枚舉類型
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 69堂永久69tangcom | 91视频亚洲 | 精品国产18久久久久久二百 | 亚洲一区久久 | 免费成人高清在线视频 | 暖暖成人免费视频 | 久久精品国产一区 | 亚洲精品女优 | 麻豆一区二区三区精品视频 | 中文在线一区二区 | 欧美激情精品久久久久 | 国产精品1| 亚洲成人在线免费 | 三级国产三级在线 | 91在线一区 | va精品| 亚洲国产一区二区三区在线观看 | 国产精品特级毛片一区二区三区 | 久久久久国产精品 | 久久91精品国产一区二区三区 | 翔田千里一区二区 | 精品国产精品一区二区夜夜嗨 | 久久99精品国产自在现线小黄鸭 | 在线91| 国产精品99久久久精品免费观看 | 国内精品视频一区二区三区 | 久久久999免费视频 999久久久久久久久6666 | 毛片av免费在线观看 | 欧美精品在欧美一区二区 | 欧美9999 | 欧美黄在线观看 | 免费一级黄色录像 | 国产美女在线观看 | 国产精品成人一区二区 | 欧美成视频 | 久久久精品天堂 | 久青草影院 | 色妞av | 91原创视频| 国产美女视频一区 | 99亚洲综合 |