數(shù)據(jù)類型
具有某種數(shù)據(jù)類型的數(shù)據(jù),稱為這個(gè)數(shù)據(jù)類型的實(shí)例活喊。如學(xué)生是類型丐膝,王小二是實(shí)例量愧。
類型可以擁有自己的成員(屬性和方法等)。 類型type指的是類帅矗、結(jié)構(gòu)偎肃、接口、委托浑此、枚舉累颂。
C#的類型包括值類型和引用類型,其中重要的類型定義成基元類型凛俱。
C#的預(yù)定義類型:8種整數(shù)型紊馏,2種2進(jìn)質(zhì)浮點(diǎn)型,1種金融十進(jìn)制浮點(diǎn)型蒲犬,1種布爾型朱监,1種字符型。
- 值類型 堆
int long char double datetime 屬于結(jié)構(gòu) 枚舉emnu
- 引用類型 棧
string class 接口 委托
引用類型只可以為null,值類型不可以
string str=null;
string str1='//n';//轉(zhuǎn)義
類實(shí)際對象的計(jì)算機(jī)語言表示原叮,擁有許多成員赫编,最重要的是屬性和方法。
對象是類的實(shí)例
屬性存儲信息和數(shù)據(jù)
方法是供我們可用的函數(shù)
運(yùn)算符和分支結(jié)構(gòu)
- 運(yùn)算符
//一元運(yùn)算符
+ - ++ --
int i=i++ i=i-- //放后是執(zhí)行完再加一
//二元運(yùn)算符
+ - * / %
== != < > <= >= //關(guān)系運(yùn)算
&& ||
+= -= *= /= %=
//三元運(yùn)算符
? :
//運(yùn)算符重載
//分支結(jié)構(gòu)
if else
switch case
方法與參數(shù)
方法method
用來把一些相關(guān)的語句收集在一起的代碼塊奋隶。方法必須有方法名擂送,擁有0個(gè)或多個(gè)參數(shù),可以有0或1個(gè)輸出唯欣,C#7后可以有多個(gè)輸出嘹吨,在這之前借助Out關(guān)鍵字實(shí)現(xiàn)多輸出。
一般定義不返回函數(shù)值得叫方法境氢,返回值的叫函數(shù)蟀拷。
C#所有數(shù)據(jù)結(jié)構(gòu):類 結(jié)構(gòu) 接口,可以有方法产还。 枚舉 不可以寫方法匹厘,委托的方法是固定的不可以自定義
方法的定義/簽名signature
- 修飾詞 public protected internal private
- 方法的返回類型。void
- 方法名稱
- 方法參數(shù)
- 實(shí)際參數(shù)和形式參數(shù)
- 按值傳遞和按引用傳遞ref
- out關(guān)鍵字的使用
- 可變關(guān)鍵字 params 數(shù)組傳參 必須在最后
//定義
public int a(params int[] b){
return 0;
}
//調(diào)用
a(1,2,3)//可變長度
- 可選參數(shù)
- 命名參數(shù)
- 遞歸調(diào)用recursion
數(shù)組與循環(huán)
- Array a =new int[10]
- 索引 從0開始 索引循環(huán)的類型是一致的
- 一維數(shù)組
- 二維數(shù)組 交錯(cuò)/齒輪數(shù)組
- 循環(huán) for foreach
- while和do while
面向?qū)ο蠛皖?/h2>
- 面向?qū)ο?object oriented
- 封裝集成多態(tài)
- 類里包括:
常量const脐区、字段field愈诚、屬性property、構(gòu)造函數(shù)牛隅、析構(gòu)函數(shù)炕柔、自定義方法、嵌套類
- 構(gòu)造函數(shù) construct
當(dāng)使用new關(guān)鍵字時(shí)媒佣,自動(dòng)調(diào)用構(gòu)造函數(shù)匕累,構(gòu)造函數(shù)名稱與類相同,public默伍,無返回值欢嘿。構(gòu)造函數(shù)可以是private(單例模式)
public class car{
public colors color{
get{
return this;
}
//set打開后衰琐,get也要打開
};
set{
this=value;//默認(rèn)value
};
}
}
- 對象初始化器
- 靜態(tài)成員
靜態(tài)方法只能使用靜態(tài)字段和屬性。
靜態(tài)成員無需實(shí)例化即可使用炼蹦。
靜態(tài)成員屬于類而非類的實(shí)例羡宙,但被所有類共享。
實(shí)例的方法可以使用靜態(tài)和實(shí)例字段和屬性掐隐。
- 靜態(tài)構(gòu)造函數(shù)
當(dāng)你的類中有靜態(tài)函數(shù)狗热,C#默認(rèn)會(huì)創(chuàng)建一個(gè)靜態(tài)構(gòu)造函數(shù),為你的靜態(tài)成員賦值虑省,不能有修飾詞匿刮,不能有輸入和輸出。靜態(tài)構(gòu)造函數(shù)只調(diào)用一次探颈。
結(jié)構(gòu)
- 結(jié)構(gòu)是值類型熟丸,可以被看作是輕量級的類
- 設(shè)計(jì)結(jié)構(gòu)是為了提升程序的性能:
引用用類型內(nèi)存的初始化需要牽扯到堆上內(nèi)存的分配,因此如果一個(gè)自定義的類型==只會(huì)包括值類型作為成員==膝擂,使用結(jié)構(gòu)是一個(gè)較好的選擇
- C#自帶的結(jié)構(gòu)有很多虑啤,包括int,DateTime等,它們的成員==全部是值類型==架馋。
- 結(jié)構(gòu)可以有自己的方法
- 結(jié)構(gòu)的成員最好是值類型
繼承inheritance
- 所有類繼承于System.Object Get.Type(反射)
- private 只用自己能訪問
- protected 自已和子類
- this當(dāng)前類型,可以用this呼叫其它構(gòu)造函數(shù)全闷,Base調(diào)用基類構(gòu)造函數(shù)
- 實(shí)例化對象會(huì)一層一層叉寂,執(zhí)行到System.Object基類
- 方法的重寫override、重載overload总珠、隱藏
- 方法隱藏屏鳍,子類和父類方法名稱相同,自動(dòng)隱藏局服,子類可以用new關(guān)鍵字
- 方法重寫钓瞭,子類和父類擁有相同的簽名方法,但子類希望得到不同的行為淫奔,而且父類的方法是虛方法或抽象方法山涡。
- 方法重載,子類和父類有相同的方法名稱唆迁,但簽名不同鸭丛。
- 密封類sealed:
- sealed修飾類型,不能補(bǔ)繼承
- sealed修飾方法唐责,不能被重寫
- 結(jié)構(gòu)是密封類型鳞溉,不能被繼承
- 抽象類abstract:必須被繼承的類
- 無法實(shí)例化一個(gè)abstract,子類必須用override來重寫它
- 不能與sealed修飾
- 比較虛的概念使用abstract
- abstract可以有普通的方法鼠哥,也可以有抽象方法
- 接口-特殊的抽象類熟菲,只能有抽象方法
- 抽象方法
- 抽象方法本身沒有方法體看政,待子類去實(shí)現(xiàn)
- 抽象方法必須在抽象類中
- 虛方法virtual
- virtual可以有方法實(shí)體,也可以沒有
- 子類可以重寫抄罕,也可以不重寫
- 用于父類可以實(shí)現(xiàn)允蚣,但子類有不同實(shí)現(xiàn)方式的情景
public class a{
int x;
int y;
public a(){}
public a(int x,int y){
this.x=x;
this.y=y;
}
}
public class b:a{
public b(int x,int y):base(x,y){}
}
多態(tài)和接口
- 多態(tài) polymorphims
- 一個(gè)類型有多種狀態(tài)。
- 接口 interface
- 接口是一種特殊的類贞绵,方法只能有簽名厉萝,而不能有方法體。
- 使用借口實(shí)現(xiàn)has-a關(guān)系榨崩。
- 使用接口實(shí)現(xiàn)多重繼承谴垫,解決單一繼承的缺陷。
- 接口就像技能母蛛,通過多重繼承賦予不同的技能翩剪。
- 策略模式
- ==依賴注入==
第三部分 數(shù)據(jù)結(jié)構(gòu)
- C# 2.0 泛型
- C# 3.0 linq
- C# 4.0 動(dòng)態(tài)語言
集和與泛型
- 數(shù)據(jù)結(jié)構(gòu) Data Sturcture
- 數(shù)據(jù)結(jié)構(gòu)是以某種形式將數(shù)據(jù)組織在一起的集合,它不僅存儲數(shù)據(jù)彩郊,還支持訪問和處理數(shù)據(jù)的操作前弯。
- 簡單分類:線性表,鏈表秫逝,哈希表恕出,樹,圖等
- 大部分編程語言都可以實(shí)現(xiàn)這些數(shù)據(jù)結(jié)構(gòu)违帆,C#已經(jīng)為我們實(shí)現(xiàn)了一部分浙巫,例如線性表(Array,List,ArrayList,Stack,Queue),鏈表(LinkedList)刷后,哈希表(HashTable,Dictionary)等等
- C#中的集合對應(yīng)了一些數(shù)據(jù)結(jié)構(gòu)
- 集合 collection
- 包括泛型集合與非泛型集合的畴,它們都是不定長的
- 非泛型集合:集合里的元素可以為任意的類型
- 泛型集合:集合里的元素只可以為一種類型T
- 從定義上,數(shù)組(Array)不是集合因?yàn)樗嵌ㄩL的
- 非泛型集合
- ArrayList
- Stack 棧
- 后進(jìn)先出(LIFO)
- 棧是限制插入和刪除只能在一個(gè)位置上進(jìn)行的線性表尝胆,該位置是表的末端丧裁,叫作棧頂,對棧的基本操作有push(進(jìn)棧)和pop(出棧)含衔,前者相當(dāng)于插入煎娇,后者相當(dāng)于刪除最后一個(gè)元素
- 練習(xí):棧中全是int,找出棧中最小的元素
- Queue 隊(duì)列
- 先進(jìn)先出(FIFO)
- 隊(duì)列是一種特殊的線性表抱慌,特殊之處在于它只允許在表的前端(front)進(jìn)行刪除操作逊桦,而在表的后端(rear)進(jìn)行插入操作,和棧一樣抑进,隊(duì)列是一種操作受限制的線性表强经。進(jìn)行插入操作的端稱為隊(duì)尾,進(jìn)行刪除操作的端稱為隊(duì)頭寺渗。
- 裝箱boxing與拆箱unboxing
-非泛型集合的兩個(gè)問題:造成裝箱和拆箱\類型不安全
- 裝箱的定義:將值類型分配給object變量
- 拆箱的定義:將object變量中的值賦給一個(gè)值類型
- 拆箱有風(fēng)險(xiǎn)匿情,操作需謹(jǐn)慎
- 泛型集合
- 泛型集合List<T>
- T稱為類型參數(shù)或占位符
- 實(shí)際使用時(shí)必須為T指定一個(gè)具體類型兰迫,例如int券坞,string等,稱為實(shí)際參數(shù)
- 棧和隊(duì)列的泛型版本
- 由于性能和類型安全万牺,出現(xiàn)泛型后以經(jīng)沒有人使用非泛型合集
- 泛型方法
- 泛型方法:輸入輸出參數(shù)包括了類型參數(shù)
- 例如:交換任意兩個(gè)同類型變量的值
- 使用泛型方法可以達(dá)到代碼復(fù)用的目的
- 泛型類型
- 可以自定義泛型結(jié)構(gòu)和類
- 例如胁澳,創(chuàng)建一個(gè)自定義的泛型結(jié)構(gòu)
- 泛型約束
- 泛型約束使得類型參數(shù)T只能是滿足某種條件的類型
- 接口約束:使得泛型的實(shí)際參數(shù)必須實(shí)現(xiàn)某個(gè)接口
- 基類型約束:實(shí)參必須是某個(gè)類的派生類
- 構(gòu)造函數(shù)約束:泛型實(shí)參必須具有可訪問的無參構(gòu)造函數(shù)(默認(rèn)的也可)
public a<T,K>(T b,K c) where T: new() where K:struct
- 可空類型
- 定義為Nullable<T> 或者用?
- 一個(gè)結(jié)構(gòu)踏拜,使用HasValue()判斷是否有值
算法介紹
- 算法 algorithm
- 定義 有限步操作的集合
- 有線性、確切性痰驱、輸入肩民、輸出蔽豺、可行性
- 時(shí)間復(fù)雜度O(S)和空間復(fù)雜度n(S)
-
- 常用數(shù)據(jù)結(jié)構(gòu)
- 線性列表
- array 定長 類型安全
- arrayList 非泛型 數(shù)據(jù)類型不安全
- List<T> 泛型
- 鏈表
- 定義:包括節(jié)點(diǎn)和下一個(gè)借點(diǎn)的引用跷车。在內(nèi)存中不連續(xù)棘利。
- 雙向鏈表則還包括前一個(gè)節(jié)點(diǎn)的引用。
- 好處:節(jié)省內(nèi)存空間朽缴,中間插入和刪除的時(shí)間復(fù)雜度底善玫。(常數(shù)復(fù)雜度,線性列表為線性)
- 壞處:不能按索引器訪問
-哈希表 hashtable
-哈希表是鍵值對數(shù)據(jù)結(jié)構(gòu)key value
-哈希函數(shù)和哈希碰撞(解決哈希碰撞密强,線性尋址法茅郎,平方尋址法)
- 插入和刪除的時(shí)間復(fù)雜度都是常數(shù),但哈希表不能排序或渤。
- 節(jié)省空間系冗,速度快
- hashtable非泛型
- Dictionary<K,T>
-
CLR(公共語言運(yùn)行時(shí))
- .net框架主要成員
- 兩部編譯和跨平臺
-中間語言IL,c#通過csc.EXE,先編譯為中間語言薪鹦,在運(yùn)行時(shí)毕谴,CLR通過JIT即使編譯為機(jī)器碼。
委托和事件
-
委托 delegate
- 委托是一個(gè)特殊的類距芬,是密封袋,不可以繼承循帐。包括一個(gè)特殊的方法invoke,也可以看成一個(gè)簽名框仔。
- 使用委托傳入方法,起到代碼復(fù)用的目的
- 可以為委托提供特殊的簽名方法
-
委托的原理:
- 委托是一個(gè)密封類拄养,它繼承自System.MulticastDelegate离斩,后者再繼承自System.Delegate
這個(gè)類的成員是固定的,這個(gè)密封類包括一個(gè)構(gòu)造函數(shù)和三個(gè)核心函數(shù)瘪匿,Invoke方法賦予其同步訪問的能力跛梗,BeginInvoke,EndInvoke賦予其異步訪問的能力
- 委托鏈:
- System.MulticastDelegate是所有委托的父類棋弥,它含有一個(gè)非常重要的字段_invocationList核偿,指的是委托自身的方法鏈,它是一個(gè)Delegate類型的數(shù)組顽染,所以委托可以掛接多于一個(gè)函數(shù)(即一個(gè)函數(shù)List)漾岳,可以為這個(gè)鏈自由的添加或刪除函數(shù)轰绵。
- 一個(gè)委托鏈可以沒有函數(shù)如果執(zhí)行委托,將會(huì)順序的執(zhí)行委托鏈上所有的函數(shù)尼荆。如果某個(gè)函數(shù)出現(xiàn)了異常左腔,則其后所有的函數(shù)都不會(huì)執(zhí)行如果你的委托的委托鏈含有很多委托的話,你只會(huì)收到最后一個(gè)含有返回值的委托的返回值
- 委托鏈?zhǔn)褂?=將方法鏈接捅儒。
- System.Delegate是System.MulticastDelegate的父類液样,它含有2個(gè)非常重要的字段_target和_methodPtr。如果委托指向了一個(gè)實(shí)例方法巧还,_target將會(huì)等于該實(shí)例本身鞭莽。在方法中,可以通過this訪問狞悲。如果委托指向了一個(gè)靜態(tài)方法撮抓,_target將會(huì)等于null無論委托指向什么方法,_methodPtr都是CLR用于標(biāo)示委托指向方法的IntPtr值
- 委托的構(gòu)造函數(shù)設(shè)置_invocationList摇锋,_target和_methodPtr在進(jìn)行調(diào)用時(shí)丹拯,Invoke方法使用_target和_methodPtr在指定對象上調(diào)用對應(yīng)的方法
-
事件
- 事件必須包括三部分:
- 事件的訂閱者(Subscriber),訂閱者會(huì)在事件觸發(fā)之后荸恕,做出響應(yīng)行為乖酬。
- 事件的觸發(fā)者,或者發(fā)布者(Publisher)融求,條件得到滿足時(shí)咬像,觸發(fā)事件訂閱者和觸發(fā)者之間的數(shù)據(jù)傳送通道。
- 事件使用步驟
- 聲明一個(gè)事件處理方法生宛,指出事件發(fā)生時(shí)县昂,訂閱者應(yīng)該有怎樣的反應(yīng)。該方法可以傳入繼承自EventArgs類型的自定義數(shù)據(jù)
- 聲明委托陷舅。委托的簽名和事件處理方法相同
- 聲明基于該委托的事件
- 為事件增加訂閱者
- 在事件符合條件時(shí)倒彰,調(diào)用事件
- 事件本身是私有的
- 事件會(huì)被轉(zhuǎn)化為一個(gè)私有的字段,以及兩個(gè)方法莱睁。字段的類型和事件關(guān)聯(lián)的委托相同待讳,而兩個(gè)方法的輸入類型和事件關(guān)聯(lián)的委托相同,沒有輸出
- 事件將字段改為私有仰剿,從而令外部不能更改它的值
- 在事件所處的對象之外创淡,事件只能出現(xiàn)在+=,-=的左方
-
泛型委托
- C# 2 中提供了兩個(gè)泛型委托Action和Func
- Action是沒有輸出的南吮,F(xiàn)unc可以有一個(gè)輸出
- 使用它們可以代替原始的delegate關(guān)鍵字
委托實(shí)際上就是函數(shù)指針琳彩,將不同函數(shù)像變量一樣傳遞,供不同參數(shù)調(diào)用。
匿名類型汁针、var關(guān)鍵字和擴(kuò)展方法
- 隱式類型
- 使用var關(guān)鍵字
- 只能對局部變量使用隱式類型
- 在foreach中一般不需要指定類型
- 匿名類型
- 匿名類型允許你直接在花括號內(nèi)建立類型术辐,而無需指定類名稱
- 只能用var或object來修飾,用var修飾可以用點(diǎn)來獲取成員
- 如果兩個(gè)匿名類型有相同的成員施无,且成員類型相同辉词,順序相同,編譯器會(huì)將它們做為同一個(gè)類型猾骡。
- 擴(kuò)展方法
- 在不創(chuàng)建子類瑞躺,不更改類型本身的情況下,修改類型
- 擴(kuò)展方法必須定義于靜態(tài)的類型中兴想,且擴(kuò)展方法必須是靜態(tài)的幢哨。
- 擴(kuò)展方法第一個(gè)輸入?yún)?shù)要加上this,擴(kuò)展方法必須至少有一個(gè)輸入?yún)?shù)
//匿名類型
var s = new { name = "小李", age = 15 };
var b=s.name;
Console.WriteLine(s.GetType());//返回<>f__AnonymousType0`2[System.String,System.Int32]
//擴(kuò)展方法
public static class StringExtension //1嫂便、在靜態(tài)類中捞镰,2、一般用Extension做為后綴
{
public static bool isHuiwen(this string input)
{
//算法
return true;
}
}
bool a = "string".isHuiwen//調(diào)用
匿名方法和lambda表達(dá)式
- 匿名方法出現(xiàn)在C#2中
- 閉包:可以使用捕獲變量(在匿名方法外部的變量)
- lambda表達(dá)式
- C#3為了令代碼更加簡化毙替,引入了lambda表達(dá)式
- lambda表達(dá)式岸售,是表達(dá)式的一種,它可以表式一個(gè)函數(shù)
- 基本結(jié)構(gòu)分三個(gè)部分
- 輸入?yún)?shù) 一個(gè)參數(shù)不需要括號厂画,多個(gè)參數(shù)或沒有參數(shù)需要括號
- 箭頭 =>
- 表達(dá)式或語名塊 如有只一條件語句不需要花括號凸丸,多行需要花括號
//old:泛型委托實(shí)現(xiàn)字符串判定
static void Main(string[] args)
{
var data = new List<string> { "string", "this", "the", "a", "dog" };
var func = new Func<string, bool>(Predicate);//泛型委托實(shí)現(xiàn),string輸入的參數(shù)袱院,bool返回的類型
//使用匿名方法的方式屎慢,不用在單獨(dú)定義Predicate這個(gè)方法
var func1 = new Func<string, bool>(delegate (string input)
{
return input.Length >= 4;
});
//lamdbe表達(dá)式寫法
Func<string, bool> func2 =(input)=>{
return input.Length >= 4;
};
foreach (var word in data)
{
if (func(word))
{
Console.WriteLine(word);
}
}
Console.ReadKey();
}
public static bool Predicate(string input)//使用匿名方法就這用寫這個(gè)了
{
return input.Length >= 4;
}
LinQ Language-Integrated Query語言結(jié)構(gòu)化查詢
-
工具準(zhǔn)備
- linQpad
- AdventureWork數(shù)據(jù)庫
-
LinQ查詢操作
LinQ分為查詢表達(dá)式和方法語法
-
查詢表達(dá)式轉(zhuǎn)換為方法語法再轉(zhuǎn)化為SQL
var data = Enumerable.Range(100, 20);
//LinQ查詢(查詢表達(dá)式)
var list1 = from s in data
where s > 115
select s;
//LinQ查詢(方法語法)
var list = data.Where(a => a > 115);
Console.WriteLine(String.Join(",", list1));
Console.ReadKey();
-
投影操作符
- Select 部分列(使用了匿名類型)
- SelectMany 在“父子表”中,使用SelectMany進(jìn)行查詢
-
過濾操作符
- Where 過濾
- Distinct 會(huì)刪除序列中重復(fù)的元素
-
排序操作符
- OrderBy 升序
- OrderByDescending 降序
- ThenBy 多列排序忽洛,放在order后繼續(xù)排序
- ThenByDescending 降序
-
分組操作符
- group by into
from p in Persons
group p by p.Name into g
select new {name=p.key,count=g.count}
var a=Persons.GroupBy(p=>p.Name)
.Select(g=>new{
name=g.Key,
Count=g.Coutn()
})
-
連接操作符
- 內(nèi)連接腻惠,左外連接和右外連接
- 在進(jìn)行內(nèi)連接時(shí),必須要指明基于哪個(gè)列
var customerList = new List<Customers>
{
new Customers{ customerId=1,Name="張三",PhoneNumber=123,Address="中國" },
new Customers{ customerId=2,Name="李四",PhoneNumber=123,Address="中國" },
new Customers{ customerId=3,Name="王五",PhoneNumber=123,Address="中國" }
};
var infoList = new List<CustomerInfo>
{
new CustomerInfo{ customerId=1, id=1,Number=70681 },
new CustomerInfo{ customerId=4, id=1,Number=70681 },
new CustomerInfo{ customerId=2, id=1,Number=70691 }
};
//連接基于兩個(gè)表欲虚,以及基于至少一列
//左聯(lián)還是右聯(lián)妖枚,基于哪個(gè)先寫
var cus = from o in infoList
join c in customerList
//基于哪個(gè)列
on o.customerId equals c.customerId
select new { c.Name, o.Number };
var cus1 = infoList.Join(customerList,
o => o.customerId,
c => c.customerId,
(o, c) => new {
c.Name, c.Address, o.Number
});
//左外連接,左邊的表中所有的數(shù)據(jù)都會(huì)出現(xiàn)在結(jié)果集中苍在,右表要給默認(rèn)值
var leftcus = from c in customerList
join o in infoList
on c.customerId equals o.customerId into p
//右表默認(rèn)值
from item in p.DefaultIfEmpty(new CustomerInfo { id = -1, Number=-1 })
select new { c.Name, c.Address, item.Number };
Console.WriteLine(String.Join("\n", leftcus));
Console.ReadKey();
-
分區(qū)操作符
- Take:從序列的開頭返回指定數(shù)量的連續(xù)元素,相當(dāng)于SQL的TOP N
- Skip:跳過序列中指定數(shù)量的元素荠商,然后返回剩余的元素
-
集合操作符
- 當(dāng)想操作兩個(gè)集合時(shí)非常有用寂恬。
- Union:并集,返回兩個(gè)序列的并集莱没,去掉重復(fù)元素初肉,相當(dāng)于SQL的Union。
- Concat:并集饰躲,返回兩個(gè)序列的并集牙咏,不處理重復(fù)元素臼隔,相當(dāng)于SQL的Union All。
- Intersect:交集妄壶,返回兩個(gè)序列中都有的元素摔握,即交集。
- Except:差集丁寄,返回只出現(xiàn)在一個(gè)序列中的元素氨淌,即差集。
-
元素操作符
- First:返回序列中的第一個(gè)元素伊磺;如果是空序列盛正,引發(fā)異常。
- FirstOrDefault:返回序列中的第一個(gè)元素屑埋;如果是空豪筝,則返回默認(rèn)值default(TSource)。
- Last:返回序列的最后一個(gè)元素摘能;如果是空序列续崖,此方法將引發(fā)異常。
- LastOrDefault:返回序列中的最后一個(gè)元素徊哑;如果是空返回默認(rèn)值default(TSource)袜刷。
- Single:返回序列的唯一元素;如果是空或多個(gè)元素莺丑,引發(fā)異常著蟹。該方法非常適合判斷序列是否只包含一個(gè)元素(并返回它)。
- SingleOrDefault:返回序列中的唯一元素梢莽;如果是空萧豆,則返回默認(rèn)值default(TSource);如果該序列包含多個(gè)元素昏名,此方法將引發(fā)異常涮雷。
-
延遲執(zhí)行
- 返回另外一個(gè)序列(通常為IEnumerable<T>或IQueryable<T>)的操作,會(huì)延遲執(zhí)行(在最終結(jié)果的第一個(gè)元素被訪問的時(shí)候才真正開始運(yùn)算)
- 返回單一值的運(yùn)算轻局,會(huì)立即執(zhí)行
- 強(qiáng)制立即執(zhí)行洪鸭,可以使用ToList()
反射和動(dòng)態(tài)語言運(yùn)行時(shí)
- dynamic關(guān)鍵字
- C#4引入動(dòng)態(tài)類型dynamic,弱類型語言
- dynamic與var的區(qū)域
- 運(yùn)行時(shí)推斷
- var不能作為方法的輸入和返回值類型,dynamic可以
- var不能修飾類或結(jié)構(gòu)的成員仑扑,dynamic可以
- 反射
- 在.net中览爵,查看和操作元數(shù)據(jù)的動(dòng)作稱為反射(Reflection)
- 通過反射加載外部程序集/類型,并調(diào)用方法
- 反射允許你訪問類型任何的成員镇饮,包括私有的
//反射
var type = typeof(ReflectionTest);
//獲得類型所有的成員
var members = type.GetMembers();
//通過反射獲得構(gòu)造函數(shù)
var constructor = type.GetConstructors()[0];
//調(diào)用構(gòu)造函數(shù)
object obj = constructor.Invoke(null);
//通過反射調(diào)用實(shí)例方法蜓竹,傳入實(shí)例
var method = type.GetMethod("AddTwo");
var o = method.Invoke(obj, new object[] { 100 });
//動(dòng)態(tài)語言運(yùn)行時(shí)提供的晚期綁定方法
//創(chuàng)建一個(gè)ReflectionTest類型的實(shí)例
//讓它是一個(gè)動(dòng)態(tài)類型
dynamic dynamicObj = Activator.CreateInstance(typeof(ReflectionTest));
//可以使用普通的方式調(diào)用方法
//編譯器不檢查,不要拼錯(cuò)
var a = dynamicObj.AddTwo(100);
- 動(dòng)態(tài)類型簡化晚期綁定
- 普通的反射
- 動(dòng)態(tài)類型使得方法呼叫更簡單
- 動(dòng)態(tài)類型簡化COM互操作
- 我們可以使用C#創(chuàng)建并修改Word,Excel文件俱济。這些都是基于COM
- 沒有動(dòng)態(tài)類型時(shí)嘶是,訪問COM對象必須使用類型強(qiáng)制轉(zhuǎn)換
- 通過動(dòng)態(tài)類型簡化代碼
C#5
常量const脐区、字段field愈诚、屬性property、構(gòu)造函數(shù)牛隅、析構(gòu)函數(shù)炕柔、自定義方法、嵌套類
當(dāng)使用new關(guān)鍵字時(shí)媒佣,自動(dòng)調(diào)用構(gòu)造函數(shù)匕累,構(gòu)造函數(shù)名稱與類相同,public默伍,無返回值欢嘿。構(gòu)造函數(shù)可以是private(單例模式)
public class car{
public colors color{
get{
return this;
}
//set打開后衰琐,get也要打開
};
set{
this=value;//默認(rèn)value
};
}
}
靜態(tài)方法只能使用靜態(tài)字段和屬性。
靜態(tài)成員無需實(shí)例化即可使用炼蹦。
靜態(tài)成員屬于類而非類的實(shí)例羡宙,但被所有類共享。
實(shí)例的方法可以使用靜態(tài)和實(shí)例字段和屬性掐隐。
當(dāng)你的類中有靜態(tài)函數(shù)狗热,C#默認(rèn)會(huì)創(chuàng)建一個(gè)靜態(tài)構(gòu)造函數(shù),為你的靜態(tài)成員賦值虑省,不能有修飾詞匿刮,不能有輸入和輸出。靜態(tài)構(gòu)造函數(shù)只調(diào)用一次探颈。
引用用類型內(nèi)存的初始化需要牽扯到堆上內(nèi)存的分配,因此如果一個(gè)自定義的類型==只會(huì)包括值類型作為成員==膝擂,使用結(jié)構(gòu)是一個(gè)較好的選擇
- 方法隱藏屏鳍,子類和父類方法名稱相同,自動(dòng)隱藏局服,子類可以用new關(guān)鍵字
- 方法重寫钓瞭,子類和父類擁有相同的簽名方法,但子類希望得到不同的行為淫奔,而且父類的方法是虛方法或抽象方法山涡。
- 方法重載,子類和父類有相同的方法名稱唆迁,但簽名不同鸭丛。
- sealed修飾類型,不能補(bǔ)繼承
- sealed修飾方法唐责,不能被重寫
- 結(jié)構(gòu)是密封類型鳞溉,不能被繼承
- 無法實(shí)例化一個(gè)abstract,子類必須用override來重寫它
- 不能與sealed修飾
- 比較虛的概念使用abstract
- abstract可以有普通的方法鼠哥,也可以有抽象方法
- 接口-特殊的抽象類熟菲,只能有抽象方法
- 抽象方法本身沒有方法體看政,待子類去實(shí)現(xiàn)
- 抽象方法必須在抽象類中
- virtual可以有方法實(shí)體,也可以沒有
- 子類可以重寫抄罕,也可以不重寫
- 用于父類可以實(shí)現(xiàn)允蚣,但子類有不同實(shí)現(xiàn)方式的情景
public class a{
int x;
int y;
public a(){}
public a(int x,int y){
this.x=x;
this.y=y;
}
}
public class b:a{
public b(int x,int y):base(x,y){}
}
- 一個(gè)類型有多種狀態(tài)。
- 接口是一種特殊的類贞绵,方法只能有簽名厉萝,而不能有方法體。
- 使用借口實(shí)現(xiàn)has-a關(guān)系榨崩。
- 使用接口實(shí)現(xiàn)多重繼承谴垫,解決單一繼承的缺陷。
- 接口就像技能母蛛,通過多重繼承賦予不同的技能翩剪。
- ==依賴注入==
- C# 2.0 泛型
- C# 3.0 linq
- C# 4.0 動(dòng)態(tài)語言
- 數(shù)據(jù)結(jié)構(gòu)是以某種形式將數(shù)據(jù)組織在一起的集合,它不僅存儲數(shù)據(jù)彩郊,還支持訪問和處理數(shù)據(jù)的操作前弯。
- 簡單分類:線性表,鏈表秫逝,哈希表恕出,樹,圖等
- 大部分編程語言都可以實(shí)現(xiàn)這些數(shù)據(jù)結(jié)構(gòu)违帆,C#已經(jīng)為我們實(shí)現(xiàn)了一部分浙巫,例如線性表(Array,List,ArrayList,Stack,Queue),鏈表(LinkedList)刷后,哈希表(HashTable,Dictionary)等等
- C#中的集合對應(yīng)了一些數(shù)據(jù)結(jié)構(gòu)
- 包括泛型集合與非泛型集合的畴,它們都是不定長的
- 非泛型集合:集合里的元素可以為任意的類型
- 泛型集合:集合里的元素只可以為一種類型T
- 從定義上,數(shù)組(Array)不是集合因?yàn)樗嵌ㄩL的
- ArrayList
- Stack 棧
- 后進(jìn)先出(LIFO)
- 棧是限制插入和刪除只能在一個(gè)位置上進(jìn)行的線性表尝胆,該位置是表的末端丧裁,叫作棧頂,對棧的基本操作有push(進(jìn)棧)和pop(出棧)含衔,前者相當(dāng)于插入煎娇,后者相當(dāng)于刪除最后一個(gè)元素
- 練習(xí):棧中全是int,找出棧中最小的元素
- Queue 隊(duì)列
- 先進(jìn)先出(FIFO)
- 隊(duì)列是一種特殊的線性表抱慌,特殊之處在于它只允許在表的前端(front)進(jìn)行刪除操作逊桦,而在表的后端(rear)進(jìn)行插入操作,和棧一樣抑进,隊(duì)列是一種操作受限制的線性表强经。進(jìn)行插入操作的端稱為隊(duì)尾,進(jìn)行刪除操作的端稱為隊(duì)頭寺渗。
- 裝箱boxing與拆箱unboxing
-非泛型集合的兩個(gè)問題:造成裝箱和拆箱\類型不安全- 裝箱的定義:將值類型分配給object變量
- 拆箱的定義:將object變量中的值賦給一個(gè)值類型
- 拆箱有風(fēng)險(xiǎn)匿情,操作需謹(jǐn)慎
- 泛型集合List<T>
- T稱為類型參數(shù)或占位符
- 實(shí)際使用時(shí)必須為T指定一個(gè)具體類型兰迫,例如int券坞,string等,稱為實(shí)際參數(shù)
- 棧和隊(duì)列的泛型版本
- 由于性能和類型安全万牺,出現(xiàn)泛型后以經(jīng)沒有人使用非泛型合集
- 泛型方法:輸入輸出參數(shù)包括了類型參數(shù)
- 例如:交換任意兩個(gè)同類型變量的值
- 使用泛型方法可以達(dá)到代碼復(fù)用的目的
- 可以自定義泛型結(jié)構(gòu)和類
- 例如胁澳,創(chuàng)建一個(gè)自定義的泛型結(jié)構(gòu)
- 泛型約束使得類型參數(shù)T只能是滿足某種條件的類型
- 接口約束:使得泛型的實(shí)際參數(shù)必須實(shí)現(xiàn)某個(gè)接口
- 基類型約束:實(shí)參必須是某個(gè)類的派生類
- 構(gòu)造函數(shù)約束:泛型實(shí)參必須具有可訪問的無參構(gòu)造函數(shù)(默認(rèn)的也可)
public a<T,K>(T b,K c) where T: new() where K:struct
- 定義為Nullable<T> 或者用?
- 一個(gè)結(jié)構(gòu)踏拜,使用HasValue()判斷是否有值
- 定義 有限步操作的集合
- 有線性、確切性痰驱、輸入肩民、輸出蔽豺、可行性
- 時(shí)間復(fù)雜度O(S)和空間復(fù)雜度n(S)
- 線性列表
- array 定長 類型安全
- arrayList 非泛型 數(shù)據(jù)類型不安全
- List<T> 泛型
- 鏈表
- 定義:包括節(jié)點(diǎn)和下一個(gè)借點(diǎn)的引用跷车。在內(nèi)存中不連續(xù)棘利。
- 雙向鏈表則還包括前一個(gè)節(jié)點(diǎn)的引用。
- 好處:節(jié)省內(nèi)存空間朽缴,中間插入和刪除的時(shí)間復(fù)雜度底善玫。(常數(shù)復(fù)雜度,線性列表為線性)
- 壞處:不能按索引器訪問
-哈希表 hashtable
-哈希表是鍵值對數(shù)據(jù)結(jié)構(gòu)key value
-哈希函數(shù)和哈希碰撞(解決哈希碰撞密强,線性尋址法茅郎,平方尋址法) - 插入和刪除的時(shí)間復(fù)雜度都是常數(shù),但哈希表不能排序或渤。
- 節(jié)省空間系冗,速度快
- hashtable非泛型
- Dictionary<K,T>
-中間語言IL,c#通過csc.EXE,先編譯為中間語言薪鹦,在運(yùn)行時(shí)毕谴,CLR通過JIT即使編譯為機(jī)器碼。
委托 delegate
- 委托是一個(gè)特殊的類距芬,是密封袋,不可以繼承循帐。包括一個(gè)特殊的方法invoke,也可以看成一個(gè)簽名框仔。
- 使用委托傳入方法,起到代碼復(fù)用的目的
- 可以為委托提供特殊的簽名方法
委托的原理:
- 委托是一個(gè)密封類拄养,它繼承自System.MulticastDelegate离斩,后者再繼承自System.Delegate
這個(gè)類的成員是固定的,這個(gè)密封類包括一個(gè)構(gòu)造函數(shù)和三個(gè)核心函數(shù)瘪匿,Invoke方法賦予其同步訪問的能力跛梗,BeginInvoke,EndInvoke賦予其異步訪問的能力 - 委托鏈:
- System.MulticastDelegate是所有委托的父類棋弥,它含有一個(gè)非常重要的字段_invocationList核偿,指的是委托自身的方法鏈,它是一個(gè)Delegate類型的數(shù)組顽染,所以委托可以掛接多于一個(gè)函數(shù)(即一個(gè)函數(shù)List)漾岳,可以為這個(gè)鏈自由的添加或刪除函數(shù)轰绵。
- 一個(gè)委托鏈可以沒有函數(shù)如果執(zhí)行委托,將會(huì)順序的執(zhí)行委托鏈上所有的函數(shù)尼荆。如果某個(gè)函數(shù)出現(xiàn)了異常左腔,則其后所有的函數(shù)都不會(huì)執(zhí)行如果你的委托的委托鏈含有很多委托的話,你只會(huì)收到最后一個(gè)含有返回值的委托的返回值
- 委托鏈?zhǔn)褂?=將方法鏈接捅儒。
- System.Delegate是System.MulticastDelegate的父類液样,它含有2個(gè)非常重要的字段_target和_methodPtr。如果委托指向了一個(gè)實(shí)例方法巧还,_target將會(huì)等于該實(shí)例本身鞭莽。在方法中,可以通過this訪問狞悲。如果委托指向了一個(gè)靜態(tài)方法撮抓,_target將會(huì)等于null無論委托指向什么方法,_methodPtr都是CLR用于標(biāo)示委托指向方法的IntPtr值
- 委托的構(gòu)造函數(shù)設(shè)置_invocationList摇锋,_target和_methodPtr在進(jìn)行調(diào)用時(shí)丹拯,Invoke方法使用_target和_methodPtr在指定對象上調(diào)用對應(yīng)的方法
事件
- 事件必須包括三部分:
- 事件的訂閱者(Subscriber),訂閱者會(huì)在事件觸發(fā)之后荸恕,做出響應(yīng)行為乖酬。
- 事件的觸發(fā)者,或者發(fā)布者(Publisher)融求,條件得到滿足時(shí)咬像,觸發(fā)事件訂閱者和觸發(fā)者之間的數(shù)據(jù)傳送通道。
- 事件使用步驟
- 聲明一個(gè)事件處理方法生宛,指出事件發(fā)生時(shí)县昂,訂閱者應(yīng)該有怎樣的反應(yīng)。該方法可以傳入繼承自EventArgs類型的自定義數(shù)據(jù)
- 聲明委托陷舅。委托的簽名和事件處理方法相同
- 聲明基于該委托的事件
- 為事件增加訂閱者
- 在事件符合條件時(shí)倒彰,調(diào)用事件
- 事件本身是私有的
- 事件會(huì)被轉(zhuǎn)化為一個(gè)私有的字段,以及兩個(gè)方法莱睁。字段的類型和事件關(guān)聯(lián)的委托相同待讳,而兩個(gè)方法的輸入類型和事件關(guān)聯(lián)的委托相同,沒有輸出
- 事件將字段改為私有仰剿,從而令外部不能更改它的值
- 在事件所處的對象之外创淡,事件只能出現(xiàn)在+=,-=的左方
泛型委托
- C# 2 中提供了兩個(gè)泛型委托Action和Func
- Action是沒有輸出的南吮,F(xiàn)unc可以有一個(gè)輸出
- 使用它們可以代替原始的delegate關(guān)鍵字
委托實(shí)際上就是函數(shù)指針琳彩,將不同函數(shù)像變量一樣傳遞,供不同參數(shù)調(diào)用。
- 使用var關(guān)鍵字
- 只能對局部變量使用隱式類型
- 在foreach中一般不需要指定類型
- 匿名類型允許你直接在花括號內(nèi)建立類型术辐,而無需指定類名稱
- 只能用var或object來修飾,用var修飾可以用點(diǎn)來獲取成員
- 如果兩個(gè)匿名類型有相同的成員施无,且成員類型相同辉词,順序相同,編譯器會(huì)將它們做為同一個(gè)類型猾骡。
- 在不創(chuàng)建子類瑞躺,不更改類型本身的情況下,修改類型
- 擴(kuò)展方法必須定義于靜態(tài)的類型中兴想,且擴(kuò)展方法必須是靜態(tài)的幢哨。
- 擴(kuò)展方法第一個(gè)輸入?yún)?shù)要加上this,擴(kuò)展方法必須至少有一個(gè)輸入?yún)?shù)
//匿名類型
var s = new { name = "小李", age = 15 };
var b=s.name;
Console.WriteLine(s.GetType());//返回<>f__AnonymousType0`2[System.String,System.Int32]
//擴(kuò)展方法
public static class StringExtension //1嫂便、在靜態(tài)類中捞镰,2、一般用Extension做為后綴
{
public static bool isHuiwen(this string input)
{
//算法
return true;
}
}
bool a = "string".isHuiwen//調(diào)用
- C#3為了令代碼更加簡化毙替,引入了lambda表達(dá)式
- lambda表達(dá)式岸售,是表達(dá)式的一種,它可以表式一個(gè)函數(shù)
- 基本結(jié)構(gòu)分三個(gè)部分
- 輸入?yún)?shù) 一個(gè)參數(shù)不需要括號厂画,多個(gè)參數(shù)或沒有參數(shù)需要括號
- 箭頭 =>
- 表達(dá)式或語名塊 如有只一條件語句不需要花括號凸丸,多行需要花括號
//old:泛型委托實(shí)現(xiàn)字符串判定
static void Main(string[] args)
{
var data = new List<string> { "string", "this", "the", "a", "dog" };
var func = new Func<string, bool>(Predicate);//泛型委托實(shí)現(xiàn),string輸入的參數(shù)袱院,bool返回的類型
//使用匿名方法的方式屎慢,不用在單獨(dú)定義Predicate這個(gè)方法
var func1 = new Func<string, bool>(delegate (string input)
{
return input.Length >= 4;
});
//lamdbe表達(dá)式寫法
Func<string, bool> func2 =(input)=>{
return input.Length >= 4;
};
foreach (var word in data)
{
if (func(word))
{
Console.WriteLine(word);
}
}
Console.ReadKey();
}
public static bool Predicate(string input)//使用匿名方法就這用寫這個(gè)了
{
return input.Length >= 4;
}
工具準(zhǔn)備
- linQpad
- AdventureWork數(shù)據(jù)庫
LinQ查詢操作
LinQ分為查詢表達(dá)式和方法語法
-
查詢表達(dá)式轉(zhuǎn)換為方法語法再轉(zhuǎn)化為SQL
var data = Enumerable.Range(100, 20); //LinQ查詢(查詢表達(dá)式) var list1 = from s in data where s > 115 select s; //LinQ查詢(方法語法) var list = data.Where(a => a > 115); Console.WriteLine(String.Join(",", list1)); Console.ReadKey();
-
投影操作符
- Select 部分列(使用了匿名類型)
- SelectMany 在“父子表”中,使用SelectMany進(jìn)行查詢
-
過濾操作符
- Where 過濾
- Distinct 會(huì)刪除序列中重復(fù)的元素
-
排序操作符
- OrderBy 升序
- OrderByDescending 降序
- ThenBy 多列排序忽洛,放在order后繼續(xù)排序
- ThenByDescending 降序
-
分組操作符
- group by into
from p in Persons group p by p.Name into g select new {name=p.key,count=g.count} var a=Persons.GroupBy(p=>p.Name) .Select(g=>new{ name=g.Key, Count=g.Coutn() })
-
連接操作符
- 內(nèi)連接腻惠,左外連接和右外連接
- 在進(jìn)行內(nèi)連接時(shí),必須要指明基于哪個(gè)列
var customerList = new List<Customers> { new Customers{ customerId=1,Name="張三",PhoneNumber=123,Address="中國" }, new Customers{ customerId=2,Name="李四",PhoneNumber=123,Address="中國" }, new Customers{ customerId=3,Name="王五",PhoneNumber=123,Address="中國" } }; var infoList = new List<CustomerInfo> { new CustomerInfo{ customerId=1, id=1,Number=70681 }, new CustomerInfo{ customerId=4, id=1,Number=70681 }, new CustomerInfo{ customerId=2, id=1,Number=70691 } }; //連接基于兩個(gè)表欲虚,以及基于至少一列 //左聯(lián)還是右聯(lián)妖枚,基于哪個(gè)先寫 var cus = from o in infoList join c in customerList //基于哪個(gè)列 on o.customerId equals c.customerId select new { c.Name, o.Number }; var cus1 = infoList.Join(customerList, o => o.customerId, c => c.customerId, (o, c) => new { c.Name, c.Address, o.Number }); //左外連接,左邊的表中所有的數(shù)據(jù)都會(huì)出現(xiàn)在結(jié)果集中苍在,右表要給默認(rèn)值 var leftcus = from c in customerList join o in infoList on c.customerId equals o.customerId into p //右表默認(rèn)值 from item in p.DefaultIfEmpty(new CustomerInfo { id = -1, Number=-1 }) select new { c.Name, c.Address, item.Number }; Console.WriteLine(String.Join("\n", leftcus)); Console.ReadKey();
-
分區(qū)操作符
- Take:從序列的開頭返回指定數(shù)量的連續(xù)元素,相當(dāng)于SQL的TOP N
- Skip:跳過序列中指定數(shù)量的元素荠商,然后返回剩余的元素
-
集合操作符
- 當(dāng)想操作兩個(gè)集合時(shí)非常有用寂恬。
- Union:并集,返回兩個(gè)序列的并集莱没,去掉重復(fù)元素初肉,相當(dāng)于SQL的Union。
- Concat:并集饰躲,返回兩個(gè)序列的并集牙咏,不處理重復(fù)元素臼隔,相當(dāng)于SQL的Union All。
- Intersect:交集妄壶,返回兩個(gè)序列中都有的元素摔握,即交集。
- Except:差集丁寄,返回只出現(xiàn)在一個(gè)序列中的元素氨淌,即差集。
-
元素操作符
- First:返回序列中的第一個(gè)元素伊磺;如果是空序列盛正,引發(fā)異常。
- FirstOrDefault:返回序列中的第一個(gè)元素屑埋;如果是空豪筝,則返回默認(rèn)值default(TSource)。
- Last:返回序列的最后一個(gè)元素摘能;如果是空序列续崖,此方法將引發(fā)異常。
- LastOrDefault:返回序列中的最后一個(gè)元素徊哑;如果是空返回默認(rèn)值default(TSource)袜刷。
- Single:返回序列的唯一元素;如果是空或多個(gè)元素莺丑,引發(fā)異常著蟹。該方法非常適合判斷序列是否只包含一個(gè)元素(并返回它)。
- SingleOrDefault:返回序列中的唯一元素梢莽;如果是空萧豆,則返回默認(rèn)值default(TSource);如果該序列包含多個(gè)元素昏名,此方法將引發(fā)異常涮雷。
延遲執(zhí)行
- 返回另外一個(gè)序列(通常為IEnumerable<T>或IQueryable<T>)的操作,會(huì)延遲執(zhí)行(在最終結(jié)果的第一個(gè)元素被訪問的時(shí)候才真正開始運(yùn)算)
- 返回單一值的運(yùn)算轻局,會(huì)立即執(zhí)行
- 強(qiáng)制立即執(zhí)行洪鸭,可以使用ToList()
- C#4引入動(dòng)態(tài)類型dynamic,弱類型語言
- dynamic與var的區(qū)域
- 運(yùn)行時(shí)推斷
- var不能作為方法的輸入和返回值類型,dynamic可以
- var不能修飾類或結(jié)構(gòu)的成員仑扑,dynamic可以
- 在.net中览爵,查看和操作元數(shù)據(jù)的動(dòng)作稱為反射(Reflection)
- 通過反射加載外部程序集/類型,并調(diào)用方法
- 反射允許你訪問類型任何的成員镇饮,包括私有的
//反射
var type = typeof(ReflectionTest);
//獲得類型所有的成員
var members = type.GetMembers();
//通過反射獲得構(gòu)造函數(shù)
var constructor = type.GetConstructors()[0];
//調(diào)用構(gòu)造函數(shù)
object obj = constructor.Invoke(null);
//通過反射調(diào)用實(shí)例方法蜓竹,傳入實(shí)例
var method = type.GetMethod("AddTwo");
var o = method.Invoke(obj, new object[] { 100 });
//動(dòng)態(tài)語言運(yùn)行時(shí)提供的晚期綁定方法
//創(chuàng)建一個(gè)ReflectionTest類型的實(shí)例
//讓它是一個(gè)動(dòng)態(tài)類型
dynamic dynamicObj = Activator.CreateInstance(typeof(ReflectionTest));
//可以使用普通的方式調(diào)用方法
//編譯器不檢查,不要拼錯(cuò)
var a = dynamicObj.AddTwo(100);
- 普通的反射
- 動(dòng)態(tài)類型使得方法呼叫更簡單
- 我們可以使用C#創(chuàng)建并修改Word,Excel文件俱济。這些都是基于COM
- 沒有動(dòng)態(tài)類型時(shí)嘶是,訪問COM對象必須使用類型強(qiáng)制轉(zhuǎn)換
- 通過動(dòng)態(tài)類型簡化代碼
C#2泛型
C#3LinQ
C#4動(dòng)態(tài)語言運(yùn)行時(shí)
C#5多線程
C#6-7
C#6-2015年7月,Vs2015 .net framework4.6語法糖
C#7-2017年3月蛛碌,Vs2017 .net framework4.6.2增加元組和模式匹配聂喇,更具有函數(shù)式語言特性
- 字符串插值
string name="張三";
string s="123";
//old
string.Format("{0}-{1}",name,s);
//new
$"{name}-{s}";
- 使用static using呼叫靜態(tài)類方法
- 為了降低代碼的冗余,我們希望在呼叫靜態(tài)類的方法時(shí)左医,可以省去類的名稱
- 判斷null的簡寫操作符授帕?.
- 利用新的操作符“?.”(稱為nullet)可以簡化代碼
- 異常過濾
- 現(xiàn)在可以在catch后面跟when子句進(jìn)一步對異常進(jìn)行過濾并操作
- 對于一些來自第三方傳回的帶有固定異常代碼的異常非常有用
- [C# 7]改進(jìn)的out關(guān)鍵字
- 現(xiàn)在,out關(guān)鍵字是即插即用的
- 允許以_(下劃線)形式“舍棄”某個(gè)out 參數(shù)
- [C# 7]值類型元組(ValueTuple)
- 元組(Tuple)是一個(gè)任意類型變量的集合浮梢,并最多支持八個(gè)變量
- C# 4中元組最大的兩個(gè)問題是:
- Tuple類將其屬性命名為 Item1跛十、Item2等,這些名稱是無法改變的秕硝,因此只會(huì)讓代碼可讀性變差
- Tuple類是引用類型芥映,使用任一Tuple類型即意味著在堆上分配對象,因此远豺,會(huì)對性能有負(fù)面影響奈偏,還不如辛苦一點(diǎn)手寫一個(gè)結(jié)構(gòu)體
- C# 7引入的新元組(ValueTuple),解決了上面兩個(gè)問題躯护,它是一個(gè)結(jié)構(gòu)體惊来,并且,你可以傳入描述性名稱(TupleElementNames屬性)以便之后更容易的調(diào)用它們
- 作為方法的參數(shù)和返回值棺滞,返回多個(gè)變量