C#高階程式設計筆記
CRL:公共語言執行庫 或者 .net執行庫,是.net framework的核心
IL(Intermediate Language):中間語言,Microsoft Intermediate Language,MSIL 微軟中間語言
JIT編輯: Just In Time Compilation 及時編輯
在.net中,編譯分為兩個階段:
1)將原始碼編譯為微軟中間語言
2)CRL將IL編譯為平臺專用的程式碼
型別判斷使用var關鍵字,編譯器根據變數的初始值推斷變數的型別
預定義資料型別:值型別,引用型別(string,Object)
值型別儲存在堆疊中,引用型別儲存在託管堆上
C#轉義字元:"C:\\Report\\image.cs" 等價於 @"C:\Report\image.cs"
列舉是使用者定義的整數型別
C#前處理器指令:
#if #else #endif #error #warning #region #endregion
#if DEBUG
console.WriteLine("x is :"+x);
#endif
可選引數:
必須為可選引數提供預設值,可選引數還必須是方法定義的最後一個引數
方法過載:
方法名稱相同,但是引數個數不同或型別不同的方法
屬性
public string Name
{
get{return _name;}
private set{_name=value;}
}
public int Age{get;private set;}
結構:結構是值型別,不支援繼承,派生自System.ValueType
struct Test{ public string length;public}
//合法,結構是值型別分配在堆疊上,宣告的時候就在棧中分配空間
//如果Test是一個類就會報錯,因為test是未初始化的引用,不指向任何地方的一個地址
Test test; test.length=5;
結構適用於小的資料結構
結構的所有內容都被複制(對於類,只複製引用),容易造成效能損失
Object類
所有的.net類都派生自System.Object,如果定義類的時候沒有指定基類,編譯器會自動假定這個類派生自Object.
System.Object()方法
ToString():為虛方法,可以在自己定義的類中重寫 public override string ToString(){.....}
GetHashCOde() Equals() Finalize() GetType() MenberwiseClone()淺複製
虛方法
把一個基類函式宣告為virtual,就可以在任何派生類中重寫該函式:
Class MyBaseClass
{
public virtual string VirtalMethod()
{
return "this method is virtual and defined in MyBaseClass";
}
}
泛型
System.Collections System.Collections.Generic
從值型別轉化成引用型別稱為裝箱
List<T>
var list=new List<int>();
var stringList=new List<string>();
var classList=new List<MyClass>();
classList.Add(new MyClass());
語法糖:指計算機語言中新增的某種語法,這種語法對語言的功能並沒有影響,但是更方便程式設計師使用。
通常來說使用語法糖能夠增加程式的可讀性,從而減少程式程式碼出錯的機會。
yield是C#的一個語法糖.
如果在語句中使用yield關鍵字,意味著它出現的方法、運算子或get訪問器是迭代器。通過使用yield定義
迭代器,可在實現自定義集合型別的IEnumerable和IEnumberator模式時無需其他顯式類
IEnumerable<T>派生自IEnumerable
協變、抗變(逆變):
所謂的協變,可以理解成:父類 -> 子類。父類的物件用子類替換,也可以理解成子類當父類用。
所謂的抗變,可以理解成:子類 -> 父類。子類的物件用父類替換,也可以理解成父類當子類用。
如果泛型型別用out關鍵字標註,泛型介面就是協變的。這也意味著返回型別只能是T
如果泛型型別用in關鍵字標註,泛型介面就是抗變的。這樣,介面只能把泛型型別T用作其方法的輸入
元組:數組合並了相同型別的物件,元組合並了不同型別的物件
可空型別 long?
型別轉換:只能從較小的整數型別隱式轉換為較大的整數型別,不能從較大的整數烈性隱式轉換為較小的整數型別
long.Parse(string) int.Parse(string) short.Parse(string) .....
委託:
把方法傳遞給其它方法時,需要用到委託。
委託是一種特殊型別的物件,以前定義的所有物件都包含資料,委託包含的只是一個或多個方法的地址。
委託的運用和類類似,先定義委託,再建立一個或多個委託的例項。
1)定義委託
委託為方法的簽名和返回型別指定名稱
委託語法類似於方法的定義,但沒有方法體,定義的前面要加上關鍵字delegate
ex:定義一個委託,該委託表示的方法包含兩個long 型的引數,返回型別為double
delegate double TwoLongsOp(long first,long second)
2)使用委託
C#中,委託的建構函式不能為空,委託在語法上總是接收一個引數的建構函式,這個引數就是委託引用的方法,這個方法必須匹配最初定義委託時的簽名
泛型Action<T>委託和Func<T>委託是系統定義的兩個泛型委託。
Action<T>委託表示引用一個返回型別為Void的方法。這個委託存在不同的變體,可以傳遞之多16個不同的引數型別。
同時,沒有泛型引數的Action類可以呼叫沒有引數的方法。例如,Action<in T>表示有一個輸入引數的方法,Action<in T1,in T2>表示有兩個輸入引數的方法。
Func<T>可以以類似的方法使用。不過Func<T>允許呼叫帶返回引數的方法。Func<T>也有不同的變體,之多可以傳遞16個引數和一個返回型別。
例如:Func<out TResult>委託型別可以無參的帶返回型別的方法,Func<in T1,inT2,out Tresult>表示帶兩個引數和一個返回型別的方法。
需要記住一個東西,Action<T>中的T可以有多個,但這些T型別都表示不同的輸入型別。Func<T>可以表示帶輸出的方法,T可以有多個,
且只有最後一個表示輸出即最後一個是返回型別。Func<in T1,inT2,out Tresult>中的字元in、out在實際程式碼中是不會出現的。在VS中,可以通過IntelliSense檢視
比較一下,其實泛型委託和自定義的委託在使用上沒什麼不同。只不過泛型委託Func<T>系統已經為我們定義好了,直接使用就可以了,
不需要再進行這樣的定義delegate double DoubleOp(double x);。另一個泛型委託Action <T>的使用也是一樣的,只不過不能有返回型別而已。
多播委託,按順序呼叫多個方法,此時委託的簽名必須是void,否則只能得到委託呼叫的最後一個方法的結果
+= -+
lambda表示式:只要有委託引數型別的地方,都可以使用lambda表示式
string mid = ",middle part,";
Func<string, string> lambda = para =>
{
para += mid;
para += " and this was added to the string.";
return para;
};
Console.WriteLine(lambda("Hello word!"));
事件:本質上是一個委託鏈。在使用事件的時候,必須要宣告對應的委託,而觸發事件,其實就是在使用委託鏈
事件釋出者、事件訂閱者(釋出者可對應多個訂閱者,1:n)
事件釋出者物件中定義委託,以及委託型別的事件,釋出事件的方法。
事件訂閱者中定義委託方法。
應用中,事件訂閱者需要在釋出者物件中註冊(即為釋出者物件事件新增委託例項),然後呼叫
釋出者物件中觸發事件的方法,即呼叫訂閱者方法。
(經典案例:裁判槍聲響起,運動員開始跑步。)
在C#的event中,委託充當了抽象的Observer介面,而提供事件的物件充當了目標物件。委託是比抽象Observer介面更為鬆耦合的設計。
.Net Framework的編碼規範:
一、委託型別的名稱都應該以EventHandler結束。 handler:處理器
二、委託的原型定義:有一個void返回值,並接受兩個輸入引數:一個Object 型別,一個 EventArgs型別(或繼承自EventArgs)。
三、事件的命名為 委託去掉 EventHandler之後剩餘的部分。
四、繼承自EventArgs的型別應該以EventArgs結尾。
觀察者模式:也被稱為釋出-訂閱(Publish/Subscribe)模式,它屬於行為型模式的一種。觀察者模式定義了一種一對多的依賴關係,
一個主題物件可被多個觀察者物件同時監聽。當這個主題物件狀態變化時,會通知所有觀察者物件並作出相應處理邏輯。
System.String 是一個類,專門用於儲存字串
StringBuilder類 兩個屬性:Length,Capacity 預設情況下Capacity比length大
當需要操作很長的字串,或者要對字串進行非常頻繁的操作時,應該使用StringBuilder,
其餘場合,用String比較方便。
StringBuilder sb=new StringBuilder("hello word!");//初始化
sb.Remove(0,sb.length);//刪除從某位置開始某一長度的字元
sb.Apend("Hello StringBuilder");//新增內榮
sb.Clear();//清空
sb.Length=111;//Length不是ReadOnly的,可修改
sb.AppendLine("this is a new Line");//新建一行
sb.ToString();//轉換為string
正則表示式:專門用於字串處理的語言。
新增引用using System.Text.RegularExpressions;
正則表示式生成器
集合:
大多數集合類都可以在System.Collections和System.Collections.Generic名稱空間中找到
泛型集合位於System.Collections.Generic名稱空間中
泛型類List<T> 實現了IList,ICollection,IEnumerable,IList<T>,ICollection<T>,IEnumerable<T>
List<T>的AddRange() 方法:一次給集合新增多個元素
var racers=new List<Racer>(20){henry,Sam,KEtty};
racers.Add(new Racer());//一次新增一個元素
racers.AddRange(new Racer(),new Racer());//一次新增多個元素
racers.Insert(index,new Racer());//在指定位置插入
.RemoveAt(index);//
.RemoveRange(index,count);//
.indexOf();//
.Find();
.Sort();
....
泛型類佇列Queue:System.Collections.Queue類標識物件的先進先出集合,
儲存在Queue(佇列)中的物件在一端插入,從另一端移除
能對集合進行順序處理,先進先出
能接受null值,允許重複的元素
Queue myQ = new Queue();//建立一個佇列
myQ.Enqueue("The");//入隊 Enqueue:將物件新增到 Queue 的結尾處。
myQ.Enqueue("quick");
myQ.Enqueue("brown");
myQ.Enqueue("fox");
myQ.Enqueue(null);//新增null
myQ.Enqueue("fox");//新增重複的元素
//Dequeue 移除並返回Queue第一個元素(佇列第一個)
Console.WriteLine("(Dequeue)\t{0}", myQ.Dequeue());
//Peek 返回位於佇列開始處的物件(第一個元素)
Console.WriteLine("(Peek) \t{0}", myQ.Peek());
// 列印佇列中的所有值
Console.Write("Queue values:");
PrintValues(myQ);
public static void PrintValues(IEnumerable myCollection)
{
foreach (Object obj in myCollection)
Console.Write(" {0}", obj);
Console.WriteLine();
}
預設值:public T GetDocument()
{
T doc =default(T)
}
棧:Stack<T>後進先出,和佇列類似都實現IEnumerable<T> 和ICollection介面
連結串列:LinkedList<T>是一個雙向連結串列
優點是將元素插入到列表中間位置時,只需要修改上一個元素的next引用以及下一個元素的previous引用。
在List<T>中插入一個元素,需要移動鈣元素後面的所有元素
有序列表:SortedList<TKey,TValue>
使用場景:需要機遇鍵對所需的集合排序
字典:Dictionary<TKey,TValue>
有序欄位:SortedDictionary<TKey,TValue>
集:包含不重複的元素的集合稱為集(set)
ISet<T>,建立合集、交集,獲取超集,子集
位陣列:如果需要處理的數字有很多位,就可以使用BitArray和BitVector32
併發集合:執行緒安全的集合類,防止多個執行緒以相互衝突的方式訪問集合
ildasm工具
Windows使用一個系統:虛擬定址系統,該系統把程式可用的記憶體地址對映到硬體記憶體中的實際地址上,這些任
由Windows在後臺管理。這些記憶體被稱為虛擬地址空間,或虛擬記憶體,一般直接叫記憶體。記憶體中有一個區域稱為棧。
棧指標:(是作業系統中維護的一個變數)指棧中下一個空閒儲存單元的地址,棧是向下填充的,即從發高記憶體地址向低記憶體地址填充。
當資料入棧後,棧指標就會隨之調整,以始終指向下一個空閒儲存單元。
託管堆(簡稱為堆):是記憶體中的另一塊區域。
指標:unsafe關鍵字 語法: int * pValue;