【C#小知識】C#中一些易混淆概念總結---------數據類型存儲,方法調用,out和ref參數的使用

這幾天一直在複習C#基礎知識,過程當中也發現了本身之前理解不清楚和混淆的概念。如今給你們分享出來個人筆記:程序員

一,.NET平臺的重要組成部分都是有哪些編程

1)FCL (所謂的.NET框架類庫)windows

這些類是微軟事先定義好的。數組

例如當咱們新建立一個windows窗體應用程序是,VS會幫咱們自動生成下面的代碼:框架

using System; using System.Collections.Generic; using System.Text;

這些就是微軟事先爲程序員定義好的類庫。程序員能夠直接使用的。編程語言

2)CLR (所謂的公共語言運行時)函數

建立部署.NET程序的必備環境spa

使用C#,F#,VB等語言均可以來建立.NET應用程序。這時候就須要一個公共語言規範,來把不一樣的語言解釋成.NET FramWork認識的東西。3d

二,什麼是程序集code

程序集主要有MSIL組成(所謂的微軟中間語言,主要由dll文件組成)

不一樣編程語言程序被.NET FrameWork編譯成程序集(dll文件),當程序須要被執行時,經過CLR中的JIT(及時編譯器)編譯成本地代碼,並將指令發送給CPU執行。

程序集通常有兩種:.dll和.exe文件(可是不是全部的dll和exe都叫程序集)

好比:咱們在同一個解決方案下,創建多個應用程序或者類庫文件。這些程序或者類庫編譯後就會變成不一樣的程序集。他們之間是相互獨立的。之間若是想要相互訪問,須要添加引用。

三,Parse轉換和Convert轉換的區別

1)Parse轉換

①Parse轉換隻能轉換字符串

②自變量是指定的數據類型才能夠轉換成功

下面的是.NET Reflector編譯的源代碼

2)Convert轉換

①能夠轉換其餘類型(如:類)

②與Parse的區別就是,轉換前會對被轉換的對象進行判斷,若是對象爲null則會轉換失敗

下面是實例源代碼:

class Program { static void Main(string[] args) { string a = Console.ReadLine(); //Parse只能夠轉換字符串
            int b = Int32.Parse(a); //Convert能夠轉換類等對象
            ParseNumber parNum = new ParseNumber(); //這種寫法編譯器會報錯 //int b = Int32.Parse(parNum);
            int c = Convert.ToInt32(parNum); Console.WriteLine(b); Console.WriteLine(b.GetType()); Console.ReadKey(); } } class ParseNumber { private int nunm; public int Num { get; set; } }

 

四,數據類型的存儲位置

1)存儲在棧中的數據類型

全部數值類型,char,bool,枚舉,結構體

2)存儲在堆中

string,數組,類

管這些類型,他們的變量的聲明都是保存在棧裏,真實的對象保存在堆裏面,棧裏面的變量存儲打的是對象的地址。

 

下面以數組來簡單說一下這個問題:

       //聲明一個一維數組
            int[] arr = new int[4];

那麼這個表達式的執行順序是什麼呢?

①首先程序會在棧中開闢一段名爲arr的int[]類型的空間

②而後在堆中開闢一個int[]對象,再該對象中會有4塊連續的內存空間

③堆中的對象返回類型爲地址,即new  int[4]表達式返回的是地址

示意圖以下:

 五,C#方法調用

1)在C#中咱們能夠給參數傳遞默認值,因此當咱們調用這個方法的時候,能夠不給這個參數傳遞值

static void Main(string[] args) { //聲明一個一維數組
            int[] arr = new int[4]; Program pro = new Program();
       //直接調用,沒有傳遞參數值 pro.para(); }
public void para(int i=5) { Console.WriteLine(i); Console.ReadKey(); }

2)帶默認參數的方法,默認值必須放在最右側

下面的寫法編譯器會報錯

3)方法的可變參數

①可變參數被Params

②Params只能用來修飾一維數組

static void Main(string[] args) { //聲明一個一維數組
            int[] arr = new int[4]; for (int i = 0; i < arr.Length; i++) { arr[i] = i; } Program pro = new Program(); pro.para(); //傳遞一位數組arr
 pro.param(arr); Console.ReadKey(); } //params用來修飾一維數組
        public void param(params int[] arr) { foreach (var item in arr) { Console.WriteLine(item); } }

③給可變參數賦值的時候能夠直接傳遞數組元素

       //聲明一個一維數組
            int[] arr = new int[4]; for (int i = 0; i < arr.Length; i++) { arr[i] = i; } Program pro = new Program(); pro.para(); //傳遞一位數組arr
 pro.param(arr); //直接傳遞數組元素,調用時會自動將這些數封裝成數組,並將數組傳遞
            pro.param(0, 1, 2, 3); Console.ReadKey();

④與默認參數同樣,可變參數的聲明必須放在方法參數的最後

4)方法的out和ref參數

①out參數側重於輸出,必須在方法內對其賦值

以下圖的聲明編譯器會報錯

正確的使用方法

       static void Main(string[] args) { //聲明參數m
            int m=0; Program pro = new Program(); //傳遞參數m,必須帶有out參數標識
            pro.outPara( out m); Console.WriteLine(m); Console.ReadKey(); } //out參數側重於輸出,必須在方法內對其賦值
        public void outPara(out int i) { //方法內部必須對out參數進行賦值
            i=5; } 

②ref參數側重於修改,可是也能夠不修改參數的值

static void Main(string[] args) { //聲明參數m
            int m=0; Program pro = new Program(); //傳遞參數m,必須帶有out參數標識
            pro.outPara( out m);
       //ref參數傳遞以前必須對其賦值,由於在方法內部可能會用到該參數 pro.refPara(
ref m); //Console.WriteLine(m); Console.ReadKey(); } // public void refPara(ref int i) { Console.WriteLine("能夠不對參數i進行任何操做!"); }

輸出結果以下:

 

六,屬性易混淆點辨別

①屬性自己不存值,值是存在這個屬性所封裝的字段裏面

class Study { private int nID; //屬性的值存儲在封裝的字段裏面
        public int NID { get { return nID; } //這裏咱們給屬性賦值
            set { nID = value; } } }

經過訪問屬性字段獲取字段的值

       Study stu = new Study(); //經過訪問屬性字段獲取字段的值
            int nID = stu.NID;

②屬性的返回值類型和字段的值類型沒有關係

     //屬性的值類型爲bool
        private bool gender; //字段的返回類型爲string
        public string Gender { get{return gender==true?"":"";} set{gender =value==""?true:false;} }

屬性的返回值類型決定了get返回值的類型和set參數的類型

     //屬性的值類型爲bool
        private bool gender; //字段的返回類型爲string
        public string Gender { //get的返回值類型爲bool
            get{return gender==true?"":"";} //set參數類型爲bool
            set{gender =value==""?true:false;} }

③自動屬性究竟是怎麼回事?

看以下的代碼:

     private string strName; //自動屬性封裝strName
        public string StrName { get; set; }

這就是所謂的自動屬性封裝字段。在非自動屬性中,程序默認的會有value值來給字段賦值,可是在自動屬性中是怎麼賦值的呢?

咱們使用.NET Reflector反編譯來看源代碼:

這是咱們封轉的屬性代碼:

反編譯set函數源代碼:

咱們能夠看到.NET會默認爲咱們的程序生成一個成員變量<StrName>k__BackingField

get函數的源代碼:

返回的也是該成員變量;

 

那麼何時能夠使用自動屬性呢?

若是對一個字段取值和賦值的時候沒有任何邏輯驗證而且可讀可寫的時候,就能夠使用自動屬性。

七,C#類聲明易混淆知識點

①首先給你們說明一個問題就是,文件名和類名必須是同樣的麼(就是咱們在建立類的時候要命明,這個時候會默認的生成同樣的類名稱)?

如圖所示

這個是必須的麼?

咱們嘗試修改類名稱爲ChildName,而後訪問類

能夠看到咱們要訪問類,須要經過類名稱訪問而與文件名沒有關係。

②類表達式的執行順序和其意義

  Study stu = new Study();

編譯器執行代碼的時候,

首先會先在棧中開闢一塊類型爲Study的內存空間放置變量stu

而後在堆中建立該變量的對象

而後調用該對象的構造函數,而且返回該對象在堆中的地址。

 

好吧,到這裏,此次的分享就到此結束了。你們若是閱讀的過程當中有什麼問題,能夠跟我留言交流。

相關文章
相關標籤/搜索