国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

CLR via C#

2019-11-17 03:17:23
字體:
來源:轉載
供稿:網友

CLR via C# - 基礎拾遺

編譯器開關設置IL代碼質量JIT本地代碼質量
/optimize- /debug-(默認設置)未優化優化
/optimize- /debug+(full/pdbonly)未優化未優化
/optimize+ /debug+(/-/full/pdbonly)優化優化

2.類型基礎,類型轉換

Object類型的方法

?GetType()為非虛方法,所以其他類型不能改變這個這個函數的返回值

從值類型調用GetType()會有一次裝箱,以將【對象類型指針】指向對應的類型(type)對象

【對象類型指針】:在CLR via C#上有講,比較清楚,堆上的對象所需要的開銷字段之一,另一個是同步塊索引

?Equal方法,重寫Equal,IEquatble<T>

Equal方法是判斷相等性,CLR via C#書上說的Object的Equal實例方法只是簡單調用==運算符,判斷的是一致性(identity),即和靜態方法ReferenceEqual一樣,我那Reflector看,最后調用的RuntimeHelper extern方法,怎么實現的也不得而知.

所有的值類型,如Struct繼承自System.ValueType,重寫的Equal如下

 1 [SecuritySafeCritical, __DynamicallyInvokable] 2 public override bool Equals(object obj) 3 { 4     if (obj == null) 5     { 6         return false; 7     } 8     RuntimeType type = (RuntimeType) base.GetType(); 9     RuntimeType type2 = (RuntimeType) obj.GetType();10     if (type2 != type)11     {12         return false;13     }14     object a = this;15     if (CanCompareBits(this))16     {17         return FastEqualsCheck(a, obj);18     }19     FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);20     for (int i = 0; i < fields.Length; i++)21     {22         object obj3 = ((RtFieldInfo) fields[i]).UnsafeGetValue(a);23         object obj4 = ((RtFieldInfo) fields[i]).UnsafeGetValue(obj);24         if (obj3 == null)25         {26             if (obj4 != null)27             {28                 return false;29             }30         }31         else if (!obj3.Equals(obj4))32         {33             return false;34         }35     }36     return true;37 }38 39  40 41  
View Code

通過比較值,我們來看看int結構的源碼

上面一個object類型參數的是重寫繼承自ValueType的Equals,下面那個是實現IEquatable<int>接口

調用的是int的==的操作符,==默認比較的引用,在ValueType類中沒有找到任何重載運算符的code,對于這個==操作符,在園子搜到的說是值類型==比較值,引用類型==比較引用,在自定義值類型如果不重載==運算符,就無法使用==運算符

Summary:對于我們自定義類型,如果要重寫Equals,也重寫下GetHashCode(),這個GetHashCode在HashTable,Dictionary中用來存儲,索引鍵,同時可以實現IEquatable<T>接口,在override的Equals中調用這個參數為T的方法.要是參與比較,可以實現IComparable<int>,可以供Equals,以及運算符重載(> >= < <=)使用

參考http://msdn.microsoft.com/zh-cn/library/ms173147.aspx

隱式轉換,強制轉換

Object o=new Person();//可以自動將new出來的Person隱式轉換Person類的任何基類

Person p=(Person)o;//強制類型轉換,顯式指定,可將一個實例強制轉換為new 類型,以及該構造類型的基類

上面的轉化在Base class,Derived class之間的轉換,不需要編寫額外的代碼.

關于Implicit(隱式)和explicit(顯式)轉換

這倆單詞總是記不住,搞混,上面的轉換是不需要code的,在不能轉換的時候,會拋出InvalidCastException,但有的時候,我們就知道怎么在不相關的實例中轉換,需要在代碼中給出轉換方法

public static implicit Operator 轉換到的類型(原類型)//implicit可以在本類里面互轉

public static implicit operator ClassA(ClassB b);//將ClassB隱式轉換為ClassA

public static implicit operator ClassB(ClassA a);//將ClassA隱式轉換為ClassB

這兩個轉換都可以在一個類中完成

public static explicit operator 轉換到的類型(本類型-即當前類)

如果要將ClassA轉為ClassB

只能在ClassA里面定義public static explicit operator ClassB(ClassA a);//顯式轉換要求被轉類型必須是當前類

msdn:http://msdn.microsoft.com/zh-cn/library/z5z9kes2.aspx

3.as is 強制類型轉換

abc as ABC等價于(abc is ABC) ?(ABC)abc :null

之前寫代碼的時候,總是想,as 和 is是哪個調用哪個呢,其實as調用is,再加強制類型轉換

我以前喜歡這樣寫

if(abc is ABC){  abc as ABC;  blabla...}

其實我這樣寫判斷了兩次abc的類型,再if里面直接用強制類型轉換即可

4.StructLayout,LayoutKind. (Auto/Sequential,Explicit)

定義struct可以看到有System.InteropServices.StructLayoutAttribute(LayoutKind.xxx)出現

這個特性可以決定CLR如何排列類 or 結構 中的字段,

Sequential:讓CLR保持字段的排列;

Auto:讓CLR來優化處理,可能會被壓縮,分組等;

Explicit:顯式地指出偏移量,來決定如何排列

結構體(Struct)默認為Sequential,經常用于與非托管C/C++代碼打交道,如果確定不用于與非托管代碼交互,可改為Auto來讓CLR優化性能

類默認就是Auto,CLR優化

5.IL中Call與Callvirt

call用來調用

?靜態方法,指定類型,方法

?實例方法,call調用實例方法時,會假設變量!=null

?特殊情況下的虛方法,非虛擬的調用虛方法,下文解釋

callvirt

?非虛實例方法,callvirt會檢查當前實例是否為null,如果是,會拋出NullReferenceException

?虛方法,call virtual,應該就是這個的縮寫,調用一個虛方法時,會查找對象的實際類型,多方面地調用虛方法...

  這個說的也是文鄒鄒的,調用虛方法

  1.如果是ABC abc=new ABC類型的,從該類以及父類中尋找被調用的方法,比較常規

  2.像Base instance=new Derived(),父類聲明,new 子類的情況,是從父類Base中開始尋找,如果找到,而且標記為virtual,而且子類中有相應的override,就調用子類的override實現,就是所謂的多態了.

在call中的第三條,call 虛方法,是這樣一種情況:在C#編譯器已知本次方法調用不會有多態存在的情況下,會生成call 虛方法指令,

例如

class Abc{  public override void ToSTring()  {    return base.ToString();//本行代碼會生成call指令,調用ToString()虛方法  }}

這個類Abc繼承自Object,重寫了ToString方法,在return base.ToSTring()時如果再用callvirt Object的ToString時,會導致遞歸調用,直至棧溢出,所以當不存在多態的情況下,虛方法調用也會生成call指令,再一個常見的是自己寫一個Struct,override一個方法,然后調用一下,絕壁生成的call,因為結構體不允許繼承,所以也沒有誰來override它的方法

6.委托

委托,事件,lambda表達式,都是很常用的東西.

委托,類似函數指針,定義一個委托之后,會被編譯成一個類,繼承自MulticastDelegate,這個MulticastDelegate又繼承自Delegate類

委托中有三個私有字段

_target 表示目標,如果委托代表的是靜態函數,那么_target即為null,若是實例成員,則_target即為這個實例

_methodPtr 函數指針,指向所代表的函數

_invocationList 表示執行鏈,當委托只是代表著一個函數時,此字段為空

委托暴露兩個公開屬性

Target:對應上面的_target

Method : MethodInfo類型,表示委托代表的函數

委托編譯成的類,會有一個構造方法(Object target,Intptr method)

一個Invoke函數,執行這個委托,還有BeginInvoke,EndInvoke 異步編程模式里面通用的

多播委托

Delegate.Combine/Delegate.Remove 可以將兩個委托連起來/剔除

而且重載了+=,-=運算符,以快速調用

在一個委托被combine了很多其他簽名符合的委托時,_target,_method均不重要了,也就是不會被調用了,而它的invocationList是被連接過的委托數組,代表著執行鏈,當委托執行時,會依次執行,但不能保證執行順序

委托語法糖

1.不需要new 委托類型(方法)了,可以直接 +=方法名

2.delegate(參){}匿名方法的出現,可以省去定義方法的步驟,以及lambda表達式,太方便了

3.delegate{},可以省去參數,當你不關心參數時,可以連括號都不用,例如在WinForm this.btn.Click+=delegate{ MessageBox(xxx);};

4.閉包支持,即在匿名方法內部可以訪問外部變量

7.屬性

屬性,get;set;訪問器也沒什么好說的.在書中,將索引器indexer叫做有參屬性

TValue this[TKey key] { [__DynamicallyInvokable] get; [__DynamicallyInvokable] set; }

這是IDictionary<TKey,TValue>接口的索引器

如果有一個IIDictionary<TKey,TValue>實例,dict

默認如果可以用dict["key"],或者dict.Items["key"]

為什么是這個Items呢,在索引器上可以有一個IndexerNameAttribute("ABC"),那樣就可以用dict.ABC["key"]來訪問,

因為屬性,索引器最后都會生成方法,來調用,編譯器可以根據這個Attribute來生成方法名稱


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 延寿县| 五家渠市| 大兴区| 凤山市| 永平县| 诏安县| 盐池县| 博野县| 喜德县| 惠州市| 三门县| 福清市| 桐柏县| 武安市| 庄浪县| 南木林县| 神木县| 方城县| 十堰市| 吉木乃县| 石门县| 鸡泽县| 前郭尔| 南城县| 大荔县| 临泽县| 视频| 五常市| 鸡泽县| 娱乐| 汾西县| 德州市| 出国| 新蔡县| 博湖县| 驻马店市| 石门县| 仙桃市| 务川| 筠连县| 桓台县|