這幾天一直在復(fù)習(xí)C#基礎(chǔ)知識(shí),過程中也發(fā)現(xiàn)了自己以前理解不清楚和混淆的概念?,F(xiàn)在給大家分享出來我的筆記:
一,.NET平臺(tái)的重要組成部分都是有哪些
1)FCL (所謂的.NET框架類庫(kù))
這些類是微軟事先定義好的。
例如當(dāng)我們新創(chuàng)建一個(gè)windows窗體應(yīng)用程序是,VS會(huì)幫我們自動(dòng)生成下面的代碼:
using System;
using System.Collections.Generic;
using System.Text;
這些就是微軟事先為程序員定義好的類庫(kù)。程序員可以直接使用的。
2)CLR (所謂的公共語言運(yùn)行時(shí))
創(chuàng)建部署.NET程序的必備環(huán)境
使用C#,F(xiàn)#,VB等語言都可以來創(chuàng)建.NET應(yīng)用程序。這時(shí)候就需要一個(gè)公共語言規(guī)范,來把不同的語言解釋成.NET FramWork認(rèn)識(shí)的東西。
二,什么是程序集
程序集主要有MSIL組成(所謂的微軟中間語言,主要由dll文件組成)
不同編程語言程序被.NET FrameWork編譯成程序集(dll文件),當(dāng)程序需要被執(zhí)行時(shí),通過CLR中的JIT(及時(shí)編譯器)編譯成本地代碼,并將指令發(fā)送給CPU執(zhí)行。
程序集一般有兩種:.dll和.exe文件(但是不是所有的dll和exe都叫程序集)
比如:我們?cè)谕粋€(gè)解決方案下,建立多個(gè)應(yīng)用程序或者類庫(kù)文件。這些程序或者類庫(kù)編譯后就會(huì)變成不同的程序集。他們之間是相互獨(dú)立的。之間如果想要相互訪問,需要添加引用。
三,Parse轉(zhuǎn)換和Convert轉(zhuǎn)換的區(qū)別
1)Parse轉(zhuǎn)換
①Parse轉(zhuǎn)換只能轉(zhuǎn)換字符串
②自變量是指定的數(shù)據(jù)類型才可以轉(zhuǎn)換成功
下面的是.NET Reflector編譯的源代碼
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-1.png" alt="" />
2)Convert轉(zhuǎn)換
①可以轉(zhuǎn)換其他類型(如:類)
②與Parse的區(qū)別就是,轉(zhuǎn)換前會(huì)對(duì)被轉(zhuǎn)換的對(duì)象進(jìn)行判斷,如果對(duì)象為null則會(huì)轉(zhuǎn)換失敗
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-2.png" alt="" />
下面是實(shí)例源代碼:
class Program
{
static void Main(string[] args)
{
string a = Console.ReadLine();
//Parse只可以轉(zhuǎn)換字符串
int b = Int32.Parse(a);
//Convert可以轉(zhuǎn)換類等對(duì)象
ParseNumber parNum = new ParseNumber();
//這種寫法編譯器會(huì)報(bào)錯(cuò)
//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; }
}
四,數(shù)據(jù)類型的存儲(chǔ)位置
1)存儲(chǔ)在棧中的數(shù)據(jù)類型
所有數(shù)值類型,char,bool,枚舉,結(jié)構(gòu)體
2)存儲(chǔ)在堆中
string,數(shù)組,類
管這些類型,他們的變量的聲明都是保存在棧里,真實(shí)的對(duì)象保存在堆里面,棧里面的變量存儲(chǔ)打的是對(duì)象的地址。
下面以數(shù)組來簡(jiǎn)單說一下這個(gè)問題:
//聲明一個(gè)一維數(shù)組
int[] arr = new int[4];
那么這個(gè)表達(dá)式的執(zhí)行順序是什么呢?
①首先程序會(huì)在棧中開辟一段名為arr的int[]類型的空間
②然后在堆中開辟一個(gè)int[]對(duì)象,再該對(duì)象中會(huì)有4塊連續(xù)的內(nèi)存空間
③堆中的對(duì)象返回類型為地址,即new int[4]表達(dá)式返回的是地址
示意圖如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-3.png" alt="" />
五,C#方法調(diào)用
1)在C#中我們可以給參數(shù)傳遞默認(rèn)值,所以當(dāng)我們調(diào)用這個(gè)方法的時(shí)候,可以不給這個(gè)參數(shù)傳遞值
static void Main(string[] args)
{
//聲明一個(gè)一維數(shù)組
int[] arr = new int[4];
Program pro = new Program();
//直接調(diào)用,沒有傳遞參數(shù)值
pro.para();
}
public void para(int i=5)
{
Console.WriteLine(i);
Console.ReadKey();
}
2)帶默認(rèn)參數(shù)的方法,默認(rèn)值必須放在最右側(cè)
下面的寫法編譯器會(huì)報(bào)錯(cuò)
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-14.png" alt="" />
3)方法的可變參數(shù)
①可變參數(shù)被Params
②Params只能用來修飾一維數(shù)組
static void Main(string[] args)
{
//聲明一個(gè)一維數(shù)組
int[] arr = new int[4];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = i;
}
Program pro = new Program();
pro.para();
//傳遞一位數(shù)組arr
pro.param(arr);
Console.ReadKey();
}
//params用來修飾一維數(shù)組
public void param(params int[] arr)
{
foreach (var item in arr)
{
Console.WriteLine(item);
}
}
③給可變參數(shù)賦值的時(shí)候可以直接傳遞數(shù)組元素
//聲明一個(gè)一維數(shù)組
int[] arr = new int[4];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = i;
}
Program pro = new Program();
pro.para();
//傳遞一位數(shù)組arr
pro.param(arr);
//直接傳遞數(shù)組元素,調(diào)用時(shí)會(huì)自動(dòng)將這些數(shù)封裝成數(shù)組,并將數(shù)組傳遞
pro.param(0, 1, 2, 3);
Console.ReadKey();
④與默認(rèn)參數(shù)一樣,可變參數(shù)的聲明必須放在方法參數(shù)的最后
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-4.png" alt="" />
4)方法的out和ref參數(shù)
①out參數(shù)側(cè)重于輸出,必須在方法內(nèi)對(duì)其賦值
如下圖的聲明編譯器會(huì)報(bào)錯(cuò)
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-5.png" alt="" />
正確的使用方法
static void Main(string[] args)
{
//聲明參數(shù)m
int m=0;
Program pro = new Program();
//傳遞參數(shù)m,必須帶有out參數(shù)標(biāo)識(shí)
pro.outPara( out m);
Console.WriteLine(m);
Console.ReadKey();
}
//out參數(shù)側(cè)重于輸出,必須在方法內(nèi)對(duì)其賦值
public void outPara(out int i)
{
//方法內(nèi)部必須對(duì)out參數(shù)進(jìn)行賦值
i=5;
}
②ref參數(shù)側(cè)重于修改,但是也可以不修改參數(shù)的值
static void Main(string[] args)
{
//聲明參數(shù)m
int m=0;
Program pro = new Program();
//傳遞參數(shù)m,必須帶有out參數(shù)標(biāo)識(shí)
pro.outPara( out m);
//ref參數(shù)傳遞之前必須對(duì)其賦值,因?yàn)樵诜椒▋?nèi)部可能會(huì)用到該參數(shù)
pro.refPara(ref m);
//Console.WriteLine(m);
Console.ReadKey();
}
//
public void refPara(ref int i)
{
Console.WriteLine("可以不對(duì)參數(shù)i進(jìn)行任何操作!");
}
輸出結(jié)果如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-13.png" alt="" />
六,屬性易混淆點(diǎn)辨別
①屬性本身不存值,值是存在這個(gè)屬性所封裝的字段里面
class Study
{
private int nID;
//屬性的值存儲(chǔ)在封裝的字段里面
public int NID
{
get { return nID; }
//這里我們給屬性賦值
set { nID = value; }
}
}
通過訪問屬性字段獲取字段的值
Study stu = new Study();
//通過訪問屬性字段獲取字段的值
int nID = stu.NID;
②屬性的返回值類型和字段的值類型沒有關(guān)系
//屬性的值類型為bool
private bool gender;
//字段的返回類型為string
public string Gender
{
get{return gender==true?"男":"女";}
set{gender =value=="男"?true:false;}
}
屬性的返回值類型決定了get返回值的類型和set參數(shù)的類型
//屬性的值類型為bool
private bool gender;
//字段的返回類型為string
public string Gender
{
//get的返回值類型為bool
get{return gender==true?"男":"女";}
//set參數(shù)類型為bool
set{gender =value=="男"?true:false;}
}
③自動(dòng)屬性到底是怎么回事?
看如下的代碼:
private string strName;
//自動(dòng)屬性封裝strName
public string StrName
{
get;
set;
}
這就是所謂的自動(dòng)屬性封裝字段。在非自動(dòng)屬性中,程序默認(rèn)的會(huì)有value值來給字段賦值,但是在自動(dòng)屬性中是怎么賦值的呢?
我們使用.NET Reflector反編譯來看源代碼:
這是我們封轉(zhuǎn)的屬性代碼:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-7.png" alt="" />
反編譯set函數(shù)源代碼:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-8.png" alt="" />
我們可以看到.NET會(huì)默認(rèn)為我們的程序生成一個(gè)成員變量k__BackingField
get函數(shù)的源代碼:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-9.png" alt="" />
返回的也是該成員變量;
那么什么時(shí)候可以使用自動(dòng)屬性呢?
如果對(duì)一個(gè)字段取值和賦值的時(shí)候沒有任何邏輯驗(yàn)證并且可讀可寫的時(shí)候,就可以使用自動(dòng)屬性。
七,C#類聲明易混淆知識(shí)點(diǎn)
①首先給大家說明一個(gè)問題就是,文件名和類名必須是一樣的么(就是我們?cè)趧?chuàng)建類的時(shí)候要命明,這個(gè)時(shí)候會(huì)默認(rèn)的生成一樣的類名稱)?
如圖所示
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-10.png" alt="" />
這個(gè)是必須的么?
我們嘗試修改類名稱為ChildName,然后訪問類
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-11.png" alt="" />
可以看到我們要訪問類,需要通過類名稱訪問而與文件名沒有關(guān)系。
②類表達(dá)式的執(zhí)行順序和其意義
編譯器執(zhí)行代碼的時(shí)候,
首先會(huì)先在棧中開辟一塊類型為Study的內(nèi)存空間放置變量stu
然后在堆中創(chuàng)建該變量的對(duì)象
然后調(diào)用該對(duì)象的構(gòu)造函數(shù),并且返回該對(duì)象在堆中的地址。
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/1-12.png" alt="" />
好吧,到這里,這次的分享就到此結(jié)束了。大家如果閱讀的過程中有什么問題,可以跟我留言交流。