c# 筆記 --自用
c# 筆記:
?
說(shuō)法或者是叫法的區(qū)別 ???(主要是區(qū)別于 c/c++ 的說(shuō)法)
?
不同的叫法:
函數(shù) = 方法
成員變量!= 屬性
(成員變量 就是變量 ?屬性是get set 倆個(gè)特殊的函數(shù))
索引器 就是c# 自己給重載了[]運(yùn)算符,另外在c#中無(wú)法重載[]運(yùn)算符
??
類型
值類型
整數(shù)類型
?
浮點(diǎn)類型
?
bool
char
enum
struct
元組類型
null
?
?
引用類型
class
interface
delegate
record
in、ref、out 參數(shù)修飾符
in?關(guān)鍵字會(huì)導(dǎo)致按引用傳遞參數(shù),但確保未修改參數(shù)。 它讓形參成為實(shí)參的別名,這必須是變量。只讀
out??只寫(xiě)
ref ?讀寫(xiě)
in只能傳參進(jìn)來(lái) ,out 只能通過(guò)函數(shù)調(diào)用修改實(shí)參。 ref 二者都可以。
?
void
空類型
var
隱式類型
?
特殊語(yǔ)法
表達(dá)式主題語(yǔ)法 expression-bodied?
?
對(duì)于函數(shù)(方法)
void func() => cwtt (void)
用于簡(jiǎn)單計(jì)算返回值的函數(shù)
只讀屬性
public class Location
{
???private string locationName;
?
???public Location(string name)
???{
??????locationName = name;
???}
?
???public string Name => locationName;
}??// Name 是只讀的
get set
public class Location
{
???private string locationName;
?
???public Location(string name) => Name = name;
?
???public string Name
???{
??????get => locationName;
??????set => locationName = value;
???}
}
?
構(gòu)造函數(shù) ??的單個(gè)賦值
析構(gòu)函數(shù)
索引器
總結(jié)就是
{// one line code ;
}
可以替換成 ?=>one line code ;
class 封裝
c#只支持單一繼承,但是一個(gè)類可以實(shí)現(xiàn)多個(gè)接口
構(gòu)造函數(shù) 與類同名 ?設(shè)置默認(rèn)值
?
索引器 :
就是一個(gè)自定義的this[] 函數(shù) ?和cpp的重載[]很像。
靜態(tài)成員:放在靜態(tài)存儲(chǔ)區(qū) ,是唯一的。只要被使用會(huì)獲得和
主程序相同的生命周期?;旧喜粫?huì)被GC。
不能使用非靜態(tài)成員變量
唯一變量的申明、方便獲取對(duì)象申明、常用的唯一方法申明
?
const?: 必須被初始化,而且只能修飾變量。const 本身是一個(gè)常量 ? ? ?
靜態(tài)類:只能有靜態(tài)成員 , 作為工具類使用。 ?不能被實(shí)例化 ? ? ?
靜態(tài)構(gòu)造函數(shù): 只有在第一次使用 會(huì)自動(dòng)調(diào)用 , 初始化靜態(tài)成員 ,就算在普通類里 ? ? 面靜態(tài)構(gòu)造也是 只會(huì)在第一次使用會(huì)自動(dòng)調(diào)用 。
拓展方法:為一個(gè)其他類拓展方法 必須是在一個(gè)靜態(tài)類中
[public]?static void?funcName(this [拓展類]?value) {} ??value 表示誰(shuí)在調(diào)用這個(gè)方法(那個(gè)實(shí)例在調(diào)用)
???? 注意:方法名和拓展方法重名后(也沒(méi)有重載的話)調(diào)用原類中的方法
?
運(yùn)算符重載:
一定是公共的靜態(tài)方法 不能使用ref out
public?static [returntyoe] operator [運(yùn)算符}{}
?
public static Point operator +(Point p1,Pointp2) // 點(diǎn)和點(diǎn)相加 ·
{
return - - ;
}
&& || ?[] ?() . ?: = ?不能重載
?
?
內(nèi)部類和分布類:
內(nèi)部類:
在類中在聲明一個(gè)類 ,而且在實(shí)例化的時(shí)候必須逐層點(diǎn)出來(lái)。
分布類:partial class Student{} ?可以有倆部分的類 同名 、而且變量不能重名
分布方法: 在一處聲明 在一處實(shí)現(xiàn)
?
class 繼承
不能多繼承 , 子類擁有父類所有的方法和屬性 但是會(huì)受到訪問(wèn)修飾符的影響
public 全訪問(wèn)權(quán)限
protected 自身 子類擁有訪問(wèn)權(quán)限
private ???只有自身?yè)碛性L問(wèn)權(quán)限
?
子類屬性和父類重名 會(huì)覆蓋父類的屬性 ??不要這么用,不建議
里氏替換原則
父類出現(xiàn)的地方,子類都可以替代
父類容器裝子類對(duì)象 ,子類對(duì)象包含父類的所有內(nèi)容
實(shí)際上就是向上轉(zhuǎn)型
is 是判斷對(duì)象是否是指定類對(duì)象
if (player is Player)??return bool
as 將一個(gè)對(duì)象轉(zhuǎn)換為指定類對(duì)象
成功會(huì)返回指定類型對(duì)象,失敗返回null
return object or null
?
繼承中的構(gòu)造函數(shù):
先調(diào)用父類的構(gòu)造函數(shù),后子類
子類實(shí)例化時(shí),默認(rèn)調(diào)用的是父類的無(wú)參構(gòu)造函數(shù),
父類的無(wú)參構(gòu)造函數(shù)被頂?shù)?,會(huì)報(bào)錯(cuò)
通過(guò)Base調(diào)用父類的構(gòu)造函數(shù)
:base() ?
?
object和 裝箱拆箱
用object 裝載任何 類進(jìn)去
引用類型需要用 is as 轉(zhuǎn)型
值類型 直接用()強(qiáng)制轉(zhuǎn)型
object 存值類型 就是裝箱
再把object轉(zhuǎn)為值類型是拆箱
?
裝箱:會(huì)把值類型用引用類型存儲(chǔ)
棧內(nèi)存會(huì)遷移到堆內(nèi)存中
拆箱:把引用類型的值取出來(lái)
堆內(nèi)存會(huì)遷移到棧內(nèi)存中
裝箱拆箱有很高的性能損耗、盡量少用
密封類:
被sealed 修飾的類 、無(wú)法被繼承
selaed class className{ } ?無(wú)法在往下被繼承
?
多態(tài)
vob:
繼承同一父類的子類們,在執(zhí)行相同方法時(shí)有不同的表現(xiàn)
編譯時(shí)多態(tài) ---- 函數(shù)重載
運(yùn)行時(shí)多態(tài) ---- vob(virtual override base )、 抽象函數(shù)、接口
vob : 父類是 virtual(虛函數(shù)) ?子類是 override(重寫(xiě)) ?、子類可以使 ? 用base保留父類的行為
抽象類和抽象方法
抽象類:
不能被實(shí)例化 ,可以包含抽象方法
一般是用于繼承的
抽象方法
abstract 關(guān)鍵字 不能實(shí)現(xiàn) 不能私有 繼承后必須被
override重寫(xiě) (virtual可以不被重寫(xiě),但是在任何類中都可以聲明和定 ? ?義)
接口
interface : 可以包含成員變量但是不能初始化 get set ?、只能包括方法、 ? ?屬性、索引器、事件
成員不能被實(shí)現(xiàn)、成員不能是私有的、不能繼承自類,但是可以繼承自其他接口
?
類可以繼承多個(gè)接口、但是必須實(shí)現(xiàn)接口中所有的成員
接口是抽象行為的基類
?
可以向上轉(zhuǎn)型
接口可以繼承多個(gè)接口
繼承倆個(gè)接口 時(shí)有重名的函數(shù)
需要顯式實(shí)現(xiàn)接口 [接口名.方法名]
?
繼承類:是對(duì)象之間的繼承,包括行為特征
繼承接口:是方法之間的繼承
就比如 游戲中的交互功能 ?可以通過(guò)交互接口來(lái)實(shí)現(xiàn)
比如 開(kāi)門(mén)、交任務(wù)、對(duì)話等等不同的行為??梢员幌嚓P(guān)類繼承
交互接口,然后自己實(shí)現(xiàn)接口,就可以實(shí)現(xiàn)相同的方法名稱有不同的作用。
密封方法:
用sealed 修飾重寫(xiě)方法 ?,讓虛方法和抽象方法不能再被override
?
命名空間:
用來(lái)管理和組織代碼的
using [命名空間]
[命名空間].funcName() ;
?
object 中的方法
static function
Euquals :判斷倆個(gè)對(duì)象是否相等(值和引用都可以)
在判斷引用類型相等時(shí) 是判斷他們是否是同一個(gè)地址(內(nèi)存空間)
ReferenceEqual() 專門(mén)用來(lái)比較引用類型 , 值類型的比較永遠(yuǎn)是false
成員方法:
GetType ?return Type ?反射內(nèi)容
?
MemberwiseClone 會(huì)獲取拷貝對(duì)象,值類型會(huì)深拷貝 、但是引用類型是淺拷貝
?
虛方法: Euqals ?可以重寫(xiě)這個(gè)方法定義自己的比較規(guī)則
?
GetHashCode 獲得對(duì)象的哈希碼、一般一個(gè)對(duì)象有一個(gè)唯一的編碼
但是不同的對(duì)象的哈希碼可能相同(哈希沖突)
可以重寫(xiě)哈希算法
ToString :返回當(dāng)前對(duì)象代表的字符串
String
字符串的本質(zhì)就是一個(gè)char數(shù)組
str.ToCharArray() 轉(zhuǎn)化為char數(shù)組
str.Format(“{0}{1}”,1,2) 字符串拼接
str.IndexOf(“”) ?正向查找字符串位置 ,沒(méi)找到 return -1
str.LastIndexOf() 反向查找字符串位置,沒(méi)找到 return -1
返回一個(gè)新的字符串
str.Remove() 移除指定位置后的字符 重載:開(kāi)始位置、字符個(gè)數(shù)
str.Replace() 替換指定字符串
str.ToUpper() ???str.ToLower()大小寫(xiě)轉(zhuǎn)換
str.Substring() ??字符串截取
str.Split(‘,’) ??字符串切割 ?以,分割 ??比如1,2,3,4 ?返回就是 1 2 3 4
StringBuilder
string 在每次重新賦值或者拼接時(shí)都會(huì)分配內(nèi)存空間
stringBuilder 用于處理字符串的公共類
修改字符串而不創(chuàng)建新的對(duì)象,需要頻繁改動(dòng)的字符串可以使用提高性能
StringBuilder str = new StringBuilder(“”,[capacity]); ?
str.Capacity 容量
增刪改查:
str.Append(); 增加
str.AppendFormat();
插入:
str.Insert();
刪除
str.Remove();
清空
str.Clear()
查找
str[] ;
改
str[]= ‘’?; StringBuilder 是可以的 ?String 這樣寫(xiě)是不行的
替換
str.Replace(“”,””);
?
結(jié)構(gòu)體和類的區(qū)別(c# 的結(jié)構(gòu)體和c++差距比較大 )
結(jié)構(gòu)體是值 在棧上 類是引用 在堆上
結(jié)構(gòu)體只能實(shí)現(xiàn)封裝 ,無(wú)法繼承和多態(tài)
結(jié)構(gòu)體是可以繼承接口的
抽象類和接口的區(qū)別
相同點(diǎn): 都可以被繼承、都不能實(shí)例化、都可以包含方法申明、
? ? ?子類必須實(shí)現(xiàn)未實(shí)現(xiàn)的方法
都可以向上轉(zhuǎn)型 (里氏替代原則)
不同點(diǎn): 抽象類中可以有構(gòu)造函數(shù) ?接口不能
抽象類只能被單一繼承 ,接口可以繼承多個(gè)
抽象類中可以有成員變量,接口不能
抽象類中可以聲明 所有的方法
接口中能能聲明沒(méi)有實(shí)現(xiàn)的抽象方法
抽象類可以使用訪問(wèn)修飾符, 接口類默認(rèn)是是public
表示對(duì)象的用抽象類 ,表示行為拓展的使用接口
?
容器 :String、 StringBuilder、 ArrayList
?
ArrayList??List<>
增加
array.Add(); ?里面可以存放任何類型的對(duì)象
array.AddRange(array2); ?
? 刪除
array.Remove(); 移除指定元素
array.RemoveAt()移除指定位置
array.Clear(); 清空
查找
array[] ;
查看元素是否在ArrayList中存在
array.Contains();
array.IndexOf() //找元素位置
array.LastIndexOf() // 反向查找元素位置
改
array[] = --- ; ?
插入
array.Insert(index,element);
遍歷
array.Count 長(zhǎng)度
array.Capacity 容量
for index 遍歷
foreach(var e in array) 迭代器遍歷 (基于范圍的for循環(huán))
裝箱拆箱??ArrayList 可能會(huì)發(fā)生裝箱拆箱 、 造成性能損耗
int i = 1 ;
array[0] = i // a裝箱
i = (int) array[0] // 拆箱
?
?
?
Stack 有Stack<T>
Stack stack = new Stack();
//壓棧
stack.Push();
//出棧
stack.Pop();
//查看棧頂?shù)膬?nèi)容
stack.Peek();
//是否存在
stack.Contains();
//改
沒(méi)法改 ,只能清空
stack.Clear();
//長(zhǎng)度
stack.Count
//用foreach 遍歷 ??--從 頂?shù)降?/p>
foreach(object item in stack)
{
}
stack.ToArray(); //轉(zhuǎn)化成數(shù)組 從頂?shù)降?/p>
//循環(huán)出棧
while(stack.Count >0)
{
object o = stack.Pop();
}
存在裝箱拆箱
?
Queue 隊(duì)列 是先進(jìn)先出 ?有 Queue<T>
Queue queue = new Queue();
增加:
queue.Enqueue();
取出:
queue.Dequeue();
查: ?隊(duì)頭元素
queue.Peek();
查看元素是否存在隊(duì)列中
queue.Contains() ;
改: ?無(wú)法改 只能清空
queue.Clear() ;
遍歷
queue.Count
foreach 遍歷
object[] array = queue.ToArray();
循環(huán)出列
while(queue.Count > 0 )
{
object e = queue.Dequeue() ;
}
?
Hashtable ??哈希表 ?散列表
Hashtable hashtable = new Hashtable();
?
增加
hashtable.Add(1,”ewq”) ; key ,value
key 不能重復(fù)
刪除:
hashtable.Remove() ; // 通過(guò)鍵去移除
hashtable.Clear() ;
查
hashtable[key] ; 查不到返回null
是否存在
hashtable.Contains(key)
hashtable.ContainsKey() 和上面一樣
hashtable.ContainsValue(); 按值找
改
無(wú)法改key 只能通過(guò) key 來(lái)改value
個(gè)數(shù)
Count
遍歷
foreach (object e in hashtable.Keys)
{
hashtable[e] ?// value ?
}
?
object e in hashtable.Values
無(wú)法 for() 遍歷
?
foreach (DictionaryEntry dir in hashtable)
{ ?dir.Key ?dir.Value ?}
?
IDictionaryEnumerator myEnumator = hashtable.GetEnumerator();
bool flag = myEnumator .MoveNext();
while(flag)
{
}
存在裝箱拆箱的情況
?
泛型
class name<T>
interface name<T>
[returntype] func<T>()
?
泛型約束:
? 值類型 where T:struct
引用類型 ???---:class
存在無(wú)參公共構(gòu)造函數(shù) --- :new()
用作泛型的類必須有無(wú)參公共構(gòu)造函數(shù)
抽象類也不行
某個(gè)類本身或者其派生類 ---:類名
某個(gè)接口的派生類型(派生類和派生接口都行) --- :接口名
另一個(gè)泛型類型本身或者派生類型 ---:另一個(gè)泛型字母
T,U ??填進(jìn)去的東西 ?T是U的派生類型 或者 T和U是一個(gè)類型
?
約束可以組合使用 (不是所有都能一起使用) ?,號(hào)分開(kāi)
?
泛型容器:
List<>?
List<int> list = new List<int>();
增加:
Add
AddRange() ;
刪除
list.Remove();
RemoveAt();
Clear()
查
list[]
是否存在
Contains() ;
正向查找
IndexOf() ?false return -1
反向查找
LastIndexOf()
改
list[1] = 23 ;
list.Insert(Index,Value);
長(zhǎng)度
Count
容量
Capacity
遍歷
for index loop
foreach loop
Dictonary<,>
Dictonary<int.string>dic = new ?Dictonary<int.string>();
增加
Add()
移除
Remove();
清空
Clear();
查
dic[2]
是否存在
ContainsKey()
ContainsValue()
?
改
dic[2] = 123
遍歷
Count
?
foreach loop Keys
foreach loop Value
foreachA(KeyValuePair<int,String> e in dic){}
順序存儲(chǔ) 鏈?zhǔn)酱鎯?chǔ)
數(shù)據(jù)結(jié)構(gòu)學(xué)過(guò)了,跳過(guò)
LinkedList<> 泛型雙向鏈表
LinkedList<int> node = new LinkedList<int>();
增加:
node.AddLast(); 尾插
AddFirst(); ??頭插
移除
RemoveFirst()
RemoveLast()
移除指定節(jié)點(diǎn)
Remove(Value)
清空
Clear()
查找
First
Last
沒(méi)法隨便找
Find(Value);
在n節(jié)點(diǎn)操作
n = node.Find(20) ; // 先要找到這個(gè)節(jié)點(diǎn)
AddAfter(n,15)
AddBefore(n,11)
改
node.First.Value = 21 ;
node.Last.Value = 123 ;
遍歷
foreach loop
while(head !=null){
node = node.next ;
} ??head next 遍歷
泛型棧和隊(duì)列 stack<> , Queue<>
委托和函數(shù)指針很類似
但是不同的點(diǎn)是 委托是一個(gè)真正的類 (所以用new來(lái)初始化)
函數(shù)指針只是一個(gè)函數(shù)的入口地址.可能委托是把函數(shù)指針?lè)庋b了一個(gè)仿函數(shù)類
核心的東西是一樣的
委托
委托是方法的容器,核心就是用來(lái)調(diào)用函數(shù)的
public delegate void delegateName(String name){}; (默認(rèn)是公共的)
定義了委托 ,并沒(méi)有使用
函數(shù)變量化 只不過(guò)里面存儲(chǔ)的是函數(shù)
delegateName d = new delegateName(FuncName) ?// 建議用這種的
d = FuncName
?
調(diào)用:
d.Invoke(); // 用這種的
d();
使用:
1.?作為類的成員變量
2.?作為函數(shù)的參數(shù)
主要就是傳遞函數(shù)給類,然后在類里面可以進(jìn)行一系列處理并且由類決定委托的調(diào)用時(shí)間和次序
多播委托(委托變量可以存儲(chǔ)多個(gè)函數(shù))
d = FuncName
d+= FuncName ??多播委托
d-=FuncName ??移除指定的函數(shù) ?多次移除指定的函數(shù)不會(huì)報(bào)錯(cuò)
把多個(gè)函數(shù)綁定給一個(gè)委托 ,委托一調(diào)用 所有的函數(shù)都我把直接執(zhí)行
委托沒(méi)有初始值的時(shí)候 ?不能使用+= ??如果初始化為null 可以使用 +=
完全清空了會(huì)直接報(bào)錯(cuò)的 ?, 所以通過(guò)委托調(diào)用函數(shù)的時(shí)候先做判空處理
if(d !=null){}
系統(tǒng)提供的委托
Action action = funName ??無(wú)參無(wú)返回值的委托
Action<> ?最多16參數(shù) 無(wú)返回值委托
Func<returnType> ?
泛型委托 Func<String> funcString = FuncName ;無(wú)參數(shù) 隨意返回值類型委托
Func<參數(shù),returnType> ?最多16個(gè)參數(shù) 有返回值委托
事件 : 建立在委托上
public event 委托類型 事件名:
事件相比委托: 不能在類外部賦初始值(綁定函數(shù)),{但是可以在外部+= ,-= 實(shí)現(xiàn)多播綁定}
不能在類外部調(diào)用
事件只能作為成員存在于類和結(jié)構(gòu)體中
class classname
{
public event?Action myEvent ;
在類內(nèi)部和委托一樣
}
事件的作用:
防止外部隨意置空委托
防止外部隨意調(diào)用委托
事件相當(dāng)于對(duì)委托進(jìn)行了一次封裝,讓其更安全
?
多線程:
進(jìn)程:一個(gè)應(yīng)用程序就是一個(gè)進(jìn)程??進(jìn)程是操作系統(tǒng)的單位
線程: ?運(yùn)算調(diào)度的最小單位 包括在進(jìn)程中是進(jìn)程中的實(shí)際操作單位,一個(gè)進(jìn)程可以并發(fā)多 ? 個(gè)線程,主程序 運(yùn)行在主線程里. 44
多線程:可以多條線程運(yùn)行代碼
線程類:Thread
Thread t =new Thread(); // 新線程的代碼是封裝在新函數(shù)中的 (形參是一個(gè)委托)
14:03
匿名函數(shù):
Action a = delegate(參數(shù)列表){}
聲明一個(gè)匿名函數(shù)放在委托里
a() ?這樣調(diào)用
Action<int,String> a = delegate(int a ,String b){}
a() 調(diào)用
?
Func<string>c = delegate() ?// return String
{
return “?“?; ??
}
作為函數(shù)傳遞給形參是委托的 ??可以傳一個(gè)匿名函數(shù)進(jìn)去
作為返回值 t.Func()() 直接調(diào)用返回的委托函數(shù)
用法: 委托的傳遞和存儲(chǔ) ??傳給函數(shù) ?和函數(shù)返回
匿名函數(shù)的缺點(diǎn)
因?yàn)闆](méi)有名字 添加到委托和事件后 不記錄是無(wú)法移除的
無(wú)法指定的移除一個(gè)匿名函數(shù)
只能 賦值為 null ?
一般單播委托使用匿名函數(shù)
lambda表達(dá)式
匿名函數(shù)的簡(jiǎn)寫(xiě) 和匿名函數(shù)一樣
語(yǔ)法: ()=>{}
無(wú)參無(wú)返回
Action a = ()=>{cw();}?;???調(diào)用 ?a()
(int value)=>{};
有返回值
Func<String,int> a = (String value)=>{return 1; }
注意這里的的String 是參數(shù) ,int (最后一個(gè))是返回值
閉包
lambda表達(dá)式 代碼塊內(nèi)使用了代碼塊外部的變量就會(huì)形成閉包,因?yàn)橥獠孔兞恳呀?jīng)進(jìn)入了堆.其生命周期得到延長(zhǎng)
內(nèi)層的函數(shù)可以引用包含在它外層的變量即使外層函數(shù)的執(zhí)行已經(jīng)終止.
表達(dá)式內(nèi) 引用了外部的變量 會(huì)導(dǎo)致 該變量閉包,
該變量生命周期改變,
?注意:該變量提供的值并非變量創(chuàng)建時(shí)的值而是父函數(shù)范圍內(nèi)的最終值
?
C#協(xié)變 ?逆變
父類裝子類 ?協(xié)變
子類裝父類 ?逆變
用來(lái)修飾泛型
?
協(xié)變 out
逆變 in ?
用來(lái)泛型中修飾泛型字母
只有泛型接口和泛型委托能用
作用:
delegate T test<out T>() ??T 只能作為返回值(out 修飾的)
能判斷 T的具體類型是否有父子關(guān)系,滿足李氏替換原則
可以父類裝子類,哪怕是泛型也可以
父類委托裝子類委托
delegate void test<in T>() ??這里的T只能用于參數(shù)(in)
?
子類裝父類 泛型委托 ?就是 逆變
c# 多線程
1.?申明線程
Thread t = new Thread(funcName);
2.啟動(dòng)線程
t.Start(); // 啟動(dòng)線程
? ? ?3.設(shè)置為后臺(tái)線程
t.IsBackgroudn() = true ;
主線程結(jié)束后 后臺(tái)線程也就結(jié)束了
(一般情況下都會(huì)設(shè)置成后臺(tái)線程)
4.關(guān)閉 釋放一個(gè)線程
不是死循環(huán)能正常結(jié)束就不用去管
是死循環(huán),倆種方法
1.?死循環(huán)的bool的標(biāo)志
2.?通過(guò)線程方法來(lái)中止線程
t.Abort(); t = null ;
Abort()不支持控制臺(tái)的版本
5.?線程休眠
Thread.Sleep(毫秒); 在那個(gè)線程里執(zhí)行就休眠那個(gè)線程
6.?線程之間共享數(shù)據(jù)
數(shù)據(jù)競(jìng)爭(zhēng)(多線程操作同一個(gè)內(nèi)存區(qū)域) 使用線程鎖
lock(引用類型)
{
// code
}
執(zhí)行完了后解鎖
鎖會(huì)影響執(zhí)行效率
作用:可以用多線程處理一些復(fù)雜耗時(shí)的操作
尋路 ?網(wǎng)絡(luò)通訊
預(yù)處理器指令
編譯器是一種翻譯程序 源語(yǔ)言程序->目標(biāo)語(yǔ)言程序
#define
#undef ??用這個(gè)定義
?
#if ?????用下面判斷 執(zhí)行 ?定義就會(huì)執(zhí)行判斷
#elif ??
#else
#endif
#error ?編譯期之前就報(bào)錯(cuò)了
反射:
程序集是由編譯器編譯得到的,供給進(jìn)一步執(zhí)行的中間文件
在window 中 有一般是dll ?和exe
?
元數(shù)據(jù):用來(lái)描述數(shù)據(jù)的數(shù)據(jù),類中的函數(shù)變量等等信息就是程序的元數(shù)據(jù)
??有關(guān)程序以及類型的數(shù)據(jù)被稱為元數(shù)據(jù),他們保存在程序集中
反射: 程序在運(yùn)行時(shí)可以查看其他程序集和其他程序集的元數(shù)據(jù)
反射的作用:
可以在程序變異后獲得信息,提高了程序的拓展性和靈活性
程序運(yùn)行時(shí),實(shí)例化對(duì)象,操作對(duì)象
程序運(yùn)行時(shí)創(chuàng)建對(duì)象,用這些對(duì)象執(zhí)行任務(wù)
Type類 (類的信息類)反射的基礎(chǔ) 使用Type成員獲取有關(guān)類型聲明的信息
int?a = 23;
Type type = a.GetType(); cw(type) ?// system.Int32
Type type = typeof(int)
通過(guò)類的名字獲取類型
Type type = Type.GetType(“System.Int32”) 必須包括命名空間
通過(guò)三種方式得到的type 只在堆中只有一個(gè) ,三個(gè)指向同一個(gè)
每一個(gè)類型的type都是唯一的,元數(shù)據(jù)是唯一的
得到類的程序集信息
type.Assembly ;
獲取類中的所有公共成員:
using System.Reflection
Type t = typeof(Test) ; // 這里Test是一個(gè)類
MemberInfo[] info = t.GetMembers();// 公共成員在這里
獲取類的公共構(gòu)造函數(shù)并調(diào)用
ConstructorInfo[] = ctors = t. ();
得到無(wú)參構(gòu)造函數(shù)
ConstructorInfo info = t.GetConstructors(new Type[0]) ;
Test obj = info.Invoke(null) as Test ;
得到有參構(gòu)造函數(shù)
ConstructorInfo info = t.GetConstructors(new Type[]{typeof(int}) ;
obj = info.Invoke(new object[]{2})as Test ;
獲取類中的公共成員變量
FieldInfo[] filedinfos = t.GetFields(); // 公共成員變量
指定名稱的公共成員變量
InfoJ = t.GetField(“j”) ??j這個(gè)成員變量
通過(guò)反射獲取和設(shè)置對(duì)象的值
InfoJ.GetValue(test);
InfoJ.SetValue(test,100) ??
獲得類的公共成員方法
Type strType = typeof(string);
MethodInfo[]methods = strType.GetMethods();
MethodInfo method = strType.GetMethod(“Substring”,
new Type[]{typeof(int),typeof(int)}
); // int,int 的函數(shù)版本
Activtor 快速的把Type類實(shí)例化對(duì)象
Type test = typeof(Test) ;
// 調(diào)用的是無(wú)參構(gòu)造函數(shù)
Test TestObj = Activator.CreateInstance(test) as Test;
?
// 調(diào)用有參構(gòu)造
Test TestObj = Activator.CreateInstance(test,參數(shù)列表) as Test;
?
Assembly
加載dll文件
Assembly asembly = Assembly.Load(“程序集名稱”);
Assembly asembly = Assembly.LoadFrom(“路徑”);
asembly.GetTypes() ;
c# 特性
特性是一個(gè)類 為元數(shù)據(jù)添加額外方法
繼承 Attribute
class MyAttribute :Attribute
{
public String info ;
public MyAttribute (String info)
{
this.info = info ;
}
}
?
[My(“”)] ??// 注意:這里的Attribute會(huì)被省略
class MyClass{}
[] 就是特性 ??為MyClass MyAttribute 添加額外信息
?
是否用類MyClass 用了 某個(gè)特性
Type t = typeof(MyClass);
if(t.IsDefined(typedof(MyAttribute),false)); ?//false 是否搜索繼承鏈
只會(huì)檢測(cè)這個(gè)類有沒(méi)有特性 ,成員 不判斷
獲取Type 元數(shù)據(jù)中的所有特性
object[] array = t.GetCustomAttribute(true);
for loop array ?
通過(guò)給特性類加特性
給特性類限制其使用范圍 AttrubuteUsage();
AttributeTargets.Class特性能用在那些地方
.Field ?成員變量
AllowMultiple ?是否允許多個(gè)特性實(shí)例用在同一個(gè)目標(biāo)上
Inherited ?特性是否能用在派生類和重寫(xiě)成員繼承
系統(tǒng)自帶的特性
1.?Obsolete 過(guò)時(shí)特性
[Obsolete(“提示內(nèi)容”),true] ?// 第二個(gè)參數(shù) true 會(huì)保存,false 會(huì)警告
public void OldFunc(){}
2.?調(diào)用者信息特性
CallerFilePath 那個(gè)文件調(diào)用
CallerLineNumber 那一行調(diào)用
CallerMemberName 那個(gè)函數(shù)調(diào)用
3.?條件編譯特性
調(diào)試代碼上
[Condition(“Func”)] // 必須要有#define Func 才可以執(zhí)行
4.?外部dll包特性
[DllImport(“路徑”)]
public static extern int Add(int a,int b); // 和 c/c++ 的函數(shù)聲明完全 一樣
迭代器
是一種設(shè)計(jì)模式
用來(lái)遍歷聚合對(duì)象的各個(gè)元素的同時(shí)不暴露內(nèi)部的標(biāo)識(shí)
:IEnumerable ?繼承這個(gè)接口 ?實(shí)現(xiàn)迭代器方法
foreach 遍歷就不會(huì)報(bào)錯(cuò) ?foreach 會(huì)調(diào)用
?public IEnumerator GetEnumerator() 方法
IEnumberator :
object Current
MoveNext()
Reset()
foreach 執(zhí)行順序
先獲取in 后面這個(gè)對(duì)象的IEnumberator
調(diào)用GetEnumerator()獲取
執(zhí)行IEnumberator 對(duì)象的MoveNext 方法
MoveNext 方法的返回值是true 就會(huì)得到Current
然后復(fù)制給 element
position ?= -1 ?// 光標(biāo)初始化
GetEnumerator()
{
Reset(); // 先重置光標(biāo)
return this;
}
MoveNext()
{
++ position ;
return position <list.Length ?不超出范圍就是合法的
}
current
{
get
{ ???return list[position] ; }
}
Reset()
{
position = -1; // 重置光標(biāo)位置
}
yield return c#語(yǔ)法糖
繼承IEnumerable,只需要實(shí)現(xiàn) GetEnumerator()
GetEnumerator()
{
for i to ?list.Length
{yield return list[i]; }
}
用yield return 實(shí)現(xiàn)迭代器
和上面完全一樣 ,只是具體的容器是使用的泛型
特殊語(yǔ)法:
1.var
var 就類似于c++里面的auto
var 必須初始化
var是可變類型
用在不確定類型
盡量少用
2.設(shè)置對(duì)象初始值 用{} 初始化公共成員變量和屬性
Person p = new Person{};
實(shí)際上沒(méi)p用
3.設(shè)置集合初始值 ?(類似于c++列表初始化)
int [] array = new int[]{1,2,3,4,5};
List<int>list = new List<int>(){1,2,3,4,5};
4.變量可以聲明為自定義的匿名類型
var v = new{} ; 只能有匿名類型
5. 可空類型
值類型不能為空 int? c = null ; 使用要判空
安全的獲得可空類型值
value.GetValueOrDefault(); 也可以指定值
6.object o = null
o?.ToString(); ?o 是否為空 不是空?qǐng)?zhí)行ToString 為空也不會(huì)報(bào)錯(cuò)
action?.Invoklel(); ?容器和委托也可以
?7.空合并操作符
int intI = intJ??100;
intJ 是否為null 不為空就賦值intJ 為空就賦值100
?8.內(nèi)插字符串
$
cw($”this is{i}”) ?i 是具體的變量名字
9.?{} 可以省略 ?for if 但是只作用于下一句
在函數(shù)、 get 、set 中 只有一句的話 {} 可以用=> 來(lái)代替
而且不能寫(xiě)return
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?