前言
工作之中,我們習慣了碰到任務就直接去實現其業務邏輯,但是C#真正的一些基礎知識,在我們久而久之不去了解鞏固的情況下,就會忽視掉。我深知自己正一步步走向只知用法卻不知原理的深淵,所以工作之餘,一直想找一些能深入講解C#基礎知識和底層原理的書籍,有幸在網上看到了《.net之美》一書,(--張子陽作 )開始只是簡單的做了閱讀,但是越往下讀,發現書中所述都是自己所薄弱或者是工作中遇到但是解釋不清其原理的知識點,為了加深自己的印象,故萌生出寫下讀書筆記的想法,也是為自己的學習有個記錄,方便日後查閱,加深理解。
一. C#語言基礎
1.1 C# 型別基礎
C#的型別共分為兩種: 值型別和引用型別. 當然,區分他們的不同是以其在計算機記憶體中的分配方式不同
來劃分的
1.值型別總是分配到它宣告的地方:
a.作為引用型別的成員變數分配到“堆”上
b.作為方法的區域性變數時分配到“棧”上
2.引用型別總是被分配到"堆"上
3.當宣告一個值型別的變數時,變數本身包含了值型別的全部欄位,該變數將被分配線上程堆疊上。
4.當宣告一個引用型別變數,並使用new操作符建立引用型別例項的時候,該引用型別的變數會被分配到執行緒棧上,變數儲存了位於堆上引用型別的例項的記憶體地址。變數本身不包含任何型別所定義的資料。
public class RefPoint
{
public int x;
public RefPoint(int x){
this.x=x;
}
public RefPoint(){};
}
當僅宣告不例項化時,RefPoint r1; 只線上程棧上建立一個不包含任何資料,也不指向任何物件 (不包含記憶體地址)的變數
當使用new操作符例項化該變數時,r1=new RefPoint(1);將完成以下幾件事
- 在應用程式堆上建立一個引用類物件的例項,併為其分配記憶體地址
- 自動傳遞該例項的引用給建構函式。
- 呼叫該型別的建構函式 public RefPoint(int x){}
- 返回該例項的引用,賦值給r1變數。
5.裝箱和拆箱
裝箱就是將一個值型別轉換成等價的引用型別,拆箱則是將一個已裝箱的引用型別轉換為值型別。
注:拆箱操作需要顯示宣告拆箱後轉換的型別。因為拆箱裝箱需要反覆在記憶體堆上進行,因此,在我們實際的程式應用中,應該避免沒有意義的裝箱和拆箱操作,以此來減少我們的記憶體消耗。
6.引用型別判等
System.Object基類中,定義了例項方法Equals(object obj)、靜態方法Equals(object objA,object objB)、靜態方法 ReferenceEquals(Object objA,Object objB) 三種方法來判斷兩個引用型別是否相等。
作者給出了以上三種方法的具體實現,如下所示:
public static bool ReferenceEquals (Object objA, Object objB)
{
return objA == objB; // #1
}
public virtual bool Equals(Object obj)
{
return InternalEquals(this, obj); // #2
}
public static bool Equals(Object objA, Object objB) {
if (objA==objB) { // #3
return true;
}
if (objA==null || objB==null) {
return false;
}
return objA.Equals(objB); // #4
}
ReferenceEquals(),判斷的是兩個引用變數是不是指向了同一個變數,如果是,則返回true,這種相等就是引用相等。等同於==。
另外需要注意的就是 對於引用型別,即使型別的例項包含的值相等,但是如果變數指向的是不同的物件,即引用值針的地址不相等,那麼這兩個變數也是不相等的。
7.簡單值型別判等
簡單值型別:值型別的成員僅包含值型別;
複雜值型別:值型別的成員包含引用型別;
值型別的判等,會呼叫System.ValueType的Equals()方法。方法內容簡單的來講就是 先判斷兩個物件是不是同一個型別,如果不是,直接返回false,接著來判斷物件內所有的欄位,利用反射機制取到值型別的所有欄位,遍歷欄位,進行欄位與欄位的比較。
8.物件複製
淺度複製:對於值型別成員,會複製其本身;對於引用型別成員,僅僅複製引用,而不在堆上重新建立物件。結果就是 新物件的引用成員和複製物件的引用成員指向了同一個物件。
相對的,深度複製:就是將引用成員指向的物件也進行復制。過程就是建立新的引用成員指向的物件,然後複製物件中所包含的資料。
9.常量性和原子性
物件的原子性:物件的狀態是一個整體,如果一個欄位改變,其他欄位也要同時做出相應改變。
如何實施?? 新增一個建構函式,在建構函式中為物件的所有欄位賦值。
物件的常量性:物件的狀態一旦確定,就不能再次更改了。如果想再次更改,需要重新建立新的物件。
如何實施??可將屬性中的set訪問器刪除,同時將欄位宣告為readonly只讀狀態。
二.小結
作者在這一章節主要講解了C#中的型別,包括值型別和引用型別,以及簡單型別和拆箱裝修的過程,以及後續的物件判等、深淺複製及物件的一些特性等。通過對此章節的閱讀,加深並鞏固了我對於C#這些基礎概念的理解,大學肯定也學過這些,但是隨著步入工作後,慢慢接觸到的都是工作中的業務邏輯處理了,關心的也是業務邏輯該如何實現等,很少再有精力去回過頭瞭解基礎的一些知識點。
今天上午還在網上看到某個大佬釋出的一篇博文,大概意思就是30+的程式設計師面試的一些過程,看完感覺感觸很深,雖然我今年27,離30+也不遠了,但是工作中,總感覺自己一旦閒下來就很慌,是那種不知所措的心裡慌,很想去看點關於基礎知識點的書籍,但是一看到知識點概念就看不進去了,偶爾還有其他事情要忙,只能草草收場,等到下次再想起來的時候,已經記不清上次自己看到哪裡了,所以寫下這篇文章也是為了防止自己再放棄,算是給自己一個鼓勵吧。
曾經問過一位博主大佬,為什麼文章寫的那麼好,感覺什麼都能拿來作文章的素材,再看看自己,雖然也在努力,但是沒有目標,沒有方向。2020年也快過完了,去年定下的目標也忘的差不多了,就希望接下來的時間裡,能抓緊時間,充實自己吧。