目錄:
成都創(chuàng)新互聯(lián)公司主營槐蔭網站建設的網絡公司,主營網站建設方案,重慶APP開發(fā)公司,槐蔭h5重慶小程序開發(fā)搭建,槐蔭網站營銷推廣歡迎槐蔭等地區(qū)企業(yè)咨詢
【C#小知識】C#中一些易混淆概念總結
----------------------------------分割線--------------------------------------
這幾天在溫習結構體和類的時候遇到一個問題。發(fā)現(xiàn)一個奇怪的現(xiàn)象,一直找不到合理的答案。但是今天終于找到了合理的答案,所以拿來和大家分享一下。
我們首先來看下面的一段代碼:
class Program { static void Main(string[] args) { Point p; Console.WriteLine(p); Point p1 = new Point(); Console.WriteLine(p1); Console.ReadKey(); } } //定義結構 struct Point { ////定義時賦初始值,編譯器會報錯 //private int x; //public Point() //{ } } class Person { //在類中我們可以為屬性賦初始值 //private int nAge = 5; //public int NAge //{ // get { return nAge; } // set { nAge = value; } //} }
當我們只是聲明一個類和一個結構體的時候,我們的編譯器順利的編譯通過。并且打印出結果如下:
為什么我們沒有在結構和類中做任何操作,卻可以打印出結果,且是“命名空間+"."+數(shù)據類型”呢?
首先我查閱了MSDN的關于結構(struct)的官方文檔(地址點擊這里),有如下的一段話:
結構默認的構造函數(shù)(如果沒有顯式聲明)在實例化的時候才會被調用。所以,
//結構的實例化可以不使用NEW關鍵字,只是將p加載到??臻g中,但是對象不可用,這里沒有調用默認的構造函數(shù) Point p2; Console.WriteLine(p2); Console.ReadKey();
在內存中是如下的情況:
此時在棧中已經存在了p這個對象,但是不可用。
那么為什么會打印出“命名空間+"."+數(shù)據類型”的結果呢?
我們先看一下VS編譯后的中間代碼,即Msil,詳細解釋在圖中給出:
有中間語言代碼,我們可以知道,最后調用的是Console.WriteLine(Object)方法
這時候就要深入的研究一下Console類了,用反編譯工具.NET Reflector查看Console類,因為在上面的代碼中,傳進.WriteLine()方法的是一個類,所以,我們要查看它的的(object value)方法,如下圖:
這時候,我們再深入到WriteLine()方法中去,源代碼,如下:
再看Out.WriteLine()的源代碼:
因為p已經在棧中創(chuàng)建了對象(但是不可用),所以,直接進入else語句。
明顯的可以發(fā)現(xiàn)IFormattable是一個接口,我們再看IFormattable接口的源碼,如下:
顯然我們的Point 結構沒有實現(xiàn)一個ToString()方法,不存在繼承關系,所以會轉化失敗,返回一個null值,又進入下一個else語句
else
{
this.WriteLine(value.ToString());
}
這時候最重要的就要來了,我們看到value值被轉換為字符串輸出了,在看ToString()源代碼,如下:
很明顯的發(fā)現(xiàn),是獲取該對象的數(shù)據類型并且轉化為字符串輸出。如下代碼:
Point p; //打印出p的數(shù)據類型 Console.WriteLine(p.GetType()); Point p2; Console.WriteLine(p2); //使用NEW實例化了對像,調用了默認的構造函數(shù) Point p1 = new Point(); Console.WriteLine(p1); Console.ReadKey();
打印結果:
這樣對結構和類的了解有沒有更深入的了解呢?
如果您覺得不錯,點擊右下角贊一下吧!您的支持,是我寫作的動力!
畢業(yè)實習交流群:221376964。你也可以關注我的新浪微博進行交流。