2018.8.14-C#复习笔记总
生活随笔
收集整理的這篇文章主要介紹了
2018.8.14-C#复习笔记总
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
2018.8.14-C#復(fù)習(xí)筆記總
using System; using System.Collections.Generic; //using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using static System.Console; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Security.Permissions; using System.Net.Sockets; using System.Net;namespace ConsoleApplication1 {class Program{[DllImport("dltest.dll", EntryPoint ="Print")]static extern void xPrint(int x);#region old-test// static void TestStreamReadWrite(){//一個流不能兼?zhèn)渥x寫兩種操作,不知道為什么,這不合理string s1 = "你好啊ABC";var t = "你好啊ABC".Length;//關(guān)于編碼注意幾點(diǎn)://1,sizeof(char) 等于 2//2,str.Length 是以元素個數(shù)算的,不是按字節(jié)算的,如 "你好啊ABC” length = 6//3,c#在VS的默認(rèn)編碼為 Encoding.Default, 該編碼下漢字占兩字節(jié),非漢字占1字節(jié),通過查看ms中的字節(jié)數(shù)據(jù)可知//4,string 類型寫入任何buffer時都是先寫長度,一般為1字節(jié),再寫字節(jié)數(shù)據(jù),如下var sz = sizeof(char); //2, 注意char占2字節(jié)var szb = sizeof(bool); //1var ms = new MemoryStream();var writer = new BinaryWriter(ms, Encoding.UTF7);writer.Write(s1);ms.Close();writer.Close();var ms2 = new MemoryStream(ms.GetBuffer());var reader = new BinaryReader(ms2, Encoding.UTF8);var s2 = reader.ReadString();}// static void TestEncoding(){string s1 = "你好啊ABC";//漢字亂碼問題,漢字必須使用2個以上字節(jié)才能表示//編碼方式//1,ASCII碼,只有一個字節(jié),不能正確表示漢字,出現(xiàn)亂碼,可以正確表示數(shù)字和字母符號//2,UNICODE,任何符號都用2個字節(jié)表示,因此可以表示漢字和任意符號//3,UTF8,變字節(jié)的編碼,可以正確表示任何字符和漢字,各國語言//4,GB2312編碼,國標(biāo)碼,主要是為漢字服務(wù)的中國編碼,漢字占兩字節(jié),字母數(shù)字占1字節(jié)//5,default編碼,在國內(nèi), 般就是GB2312 Encoding.Default.GetBytes(s1);var bytes = Encoding.GetEncoding("GB2312").GetBytes(s1);var len = bytes.Length;var bts = new byte[10 + len];Array.ConstrainedCopy(bytes, 0, bts, 0, len);var s2 = Encoding.GetEncoding("GB2312").GetString(bts).TrimEnd('\0');string s3 = "\0hello/0/0dddddd".TrimStart('\0');//!!!!!!!!!!!!!!!!!!!!!!!!!!!! }#region 計算機(jī)中數(shù)據(jù)的存儲// static void TestTypeConvert(){//把一個有符號數(shù)轉(zhuǎn)為無符號后再轉(zhuǎn)回來值保持不變,以下以1字節(jié)為例//原理:計算機(jī)中符點(diǎn)數(shù)都是有符號的,不存在這種轉(zhuǎn)變,只剩下整數(shù),//真值:絕對值的二進(jìn)制值,如-1的真值為 00000001//整數(shù)是以補(bǔ)碼形式存放的,計算機(jī)規(guī)定了正數(shù)的補(bǔ)碼是本身,負(fù)數(shù)的補(bǔ)碼是:符號位不變,真值按位取反再加1//強(qiáng)制轉(zhuǎn)換做的事就是把一個補(bǔ)碼看成是有符號還是無符號//有符號數(shù),在計算時:符號位不變,真值按位取反再加1。無符號數(shù)直接計算,舉例如下://1,-1 的真值為00000001,補(bǔ)碼為 1 111 1111,強(qiáng)轉(zhuǎn)時就是把補(bǔ)碼值看作是一個無符數(shù),因此它=255//,再次強(qiáng)轉(zhuǎn)時把它看成有符號數(shù),符號位不管,其余位按位取反加1后是1,因此再次轉(zhuǎn)回了-1//2,-2 的真值為00000010,補(bǔ)碼為 1 111 1110,強(qiáng)轉(zhuǎn)時把補(bǔ)碼看作無符號數(shù),因此它=254//3,-128真值有點(diǎn)特殊,128的二進(jìn)制碼為1000 0000,第8位是符號位,舍棄,取后面的0,即-128的真值為0//補(bǔ)碼經(jīng)按位取反加1后還是 1 000 0000,強(qiáng)轉(zhuǎn)時看成無符號數(shù)即為128//-------------------------------------------//1字節(jié)數(shù)據(jù)和2字節(jié)數(shù)據(jù)進(jìn)行加法運(yùn)算時,要進(jìn)行位擴(kuò)展,將1字節(jié)擴(kuò)展為2字節(jié)//正數(shù)擴(kuò)展時高位補(bǔ)0,負(fù)數(shù)擴(kuò)展時高位補(bǔ)1//C#中小于4字節(jié)的數(shù)據(jù)進(jìn)行運(yùn)算時會先擴(kuò)展成int再進(jìn)行sbyte sb = -127;var b = (byte)(sb);var sb1 = (sbyte)(b);object dx = 10.0f;double dx2 = 33;byte ix = (byte)dx2;var t = dx.GetType();Type T = System.Type.GetType(t.FullName, true);}#endregion// void TestUncheck(){unchecked{//不被編譯系統(tǒng)做編譯時安全檢查 }}static void TestBoxing(){int i = 10;object o = 1;int i2 = (int)o;}static void TestReadBytes(){byte[] bts = new byte[4] { 23, 0, 16, 0 };var ms = new MemoryStream(bts);var br = new BinaryReader(ms);var p1 = ms.Position;var ix = br.ReadUInt32();var p2 = ms.Position;Console.WriteLine("num=" + ix);br.Dispose();br.Close();ms.Dispose();ms.Close();}static void TestStrEnd(){string str = "abcde\0";var br = new BinaryReader(new MemoryStream(Encoding.ASCII.GetBytes(str)));var b = br.ReadByte();while (b != 0){Console.WriteLine(b);try{b = br.ReadByte();}catch (System.Exception ex){Console.WriteLine("未發(fā)現(xiàn)字符串結(jié)束符");break;}}}static void TestBigEndia(){var br = new BinaryWriter(File.Create("f:/testx.dt"), Encoding.ASCII);br.Write((Int16)9);string str = "Stand";br.Write(str);br.Write((Int16)10);br.Write((Int16)70);br.Dispose();}static void TestChar0(){//注意字符串中0和\0的區(qū)別,如 s1="h0ello", s2 = "h\0ello"//s2中的\0是字符串結(jié)尾符,除了C#不把它作為結(jié)束符外,其它語言都把它作為結(jié)束符,如U3D,LUA,C/C++等//而s1中的0僅是一個字符0而已,字符0的ASCII值是0X31=49,'\0'的ASCII值是0//注意這兩種0在C#和U3D的API之間切換時容易造成BUG,如://1, debug.log(s1): "h0ello"//2,debug.log(s2): "h"var s = "hello";s += 0 + ",world";var s1 = "hello";s1 += (char)0 + ",world";var s2 = "hello";s2 += '\0' + ",world";}static void MemTest(){}static void ReflectionTest(){//測試兩種反射的效率問題//Type.GetType()只能在同一個程序集中使用,typeof則可以跨程序集(assembly)//通過下面的實(shí)測,發(fā)現(xiàn)typeof是比GetType快40多倍var timer = Stopwatch.StartNew();timer.Start();Type tx = Type.GetType("string");var tx1 = Type.GetType("float");timer.Stop();Console.WriteLine("T1= " + timer.Elapsed);//0.0000471 timer.Restart();tx = typeof(string);tx1 = typeof(float);timer.Stop();Console.WriteLine("T2= " + timer.Elapsed);//0.0000011 }static void TestDelegate(){//類C++11風(fēng)格:指定初始化容量20,使用初始化列表給部分成員賦值var lst = new List<float>(20) { 1, 3, 4, 20, -2, 9, 0 };for (var i = 0; i < lst.Count; ++i){//使用下標(biāo)進(jìn)行隨機(jī)訪問,說明list不是一個真正的鏈表,而是類似STL的Vector Console.WriteLine(lst[i]);}//public void Sort (Comparison<T> comparison) //public delegate int Comparison<T>(T x, T y);//這是對調(diào)用List<int>.Sort進(jìn)行排序的寫法,其中sort的定義及Comparison委托的定義如上lst.Sort(new Comparison<float>(delegate (float m1, float m2) //委托 {return 1;}));lst.Sort(delegate (float m1, float m2) //委托 {return 1;});lst.Sort((float m1, float m2) =>//Linq表達(dá)式 {return 1;});lst.Sort((m1, m2) => //Linq表達(dá)式 {return 1;});}static string TestRetStr(){//測試返回字符串是否會復(fù)制return "helloworld";}static void TestStrRet(){//h1 = h2 = h3說明它們返回的是同一個字符串的引用var s1 = TestRetStr();var s2 = TestRetStr();var s3 = TestRetStr();var h1 = s1.GetHashCode();var h2 = s1.GetHashCode();var h3 = s1.GetHashCode();}static void TestVirtualFuncCall(){var otx = new CTestChildX();otx.Update();//輸出結(jié)果:child,如果注釋1處函數(shù)不加override,輸出結(jié)果為:basevar oty = new CTestY();oty.Update();oty.OnUpdate();}static void TestStrModify(){var s1 = "hello";var s2 = s1;s1 += "world";Console.WriteLine(s2);var uns1 = s2.GetHashCode();Console.WriteLine(uns1);}static void Tests1(){var s1 = "hello";var uns1 = s1.GetHashCode();Console.WriteLine(uns1);}#endregion#region 2018.3.30#region ref out and templateclass myTemp<T1, T2>//類入口 {public T1 Add(T1 a, T1 b){//模板類型不能直接相加,必須先轉(zhuǎn)為動態(tài)類型,避開編譯檢查,運(yùn)行時動態(tài)決定類型dynamic da = a;dynamic db = b;return da + db;}public void tint<T3>()//注意C++不能這么寫,所有模板參數(shù)必須由類入口傳入 {Type t = typeof(T3);WriteLine(t);}}delegate void refOutFunc(ref double t1, out double t2);delegate T TemplateDelegate<T, U>(T a, U b);static void TestRefAndOut(){//ref, out 本質(zhì)上都是引用//fef就為了傳給函數(shù)使用,必須先初始化,但也可以傳出數(shù)據(jù),out是為了從函數(shù)中傳出數(shù)據(jù)使用,不用初始化refOutFunc rof = delegate (ref double ax, out double bx) {ax = 1; bx = 2;//ref out兩種類型的變量都被更改了 };double x1 = 0, x2;rof(ref x1, out x2);}static void TestTemplate(){var otp = new myTemp<int, int>();otp.tint<object>();}static T TempFunc<T, U>(T a, U b){return a;}static void TestBufAligin(){//自定義字節(jié)BUF的對齊測試int x = 9;int y = (x + 7) & ~7;WriteLine(y);}#endregion#endregion#region 2018.4.9//BUG??????//使用StopWatch測試運(yùn)行時間//兩段測試A和B//測試結(jié)果受測試順序影響,后測要比先測耗時長了許多static void TestKeyIntStr(){// var idict = new Dictionary<int, string>();var sdict = new Dictionary<string, string>();for (int i = 0; i < 1000000; i++){var key = i * 2 + 1;var v = i * i + "";idict.Add(key, v);sdict.Add(key + "", v);}//測試 Avar t1 = 100000 * Test1(idict);//測試 Bvar t2 = 100000 * Test2(sdict);Console.WriteLine("t1: {0},t2: {1}", t1, t2);//Console.WriteLine("dt1: {0},dt2: {1}", dt1, dt2); }static float Test1(Dictionary<int, string> dict){var timer = new Stopwatch();timer.Start();var it = dict[2001];var t1 = timer.ElapsedTicks;timer.Stop();return (float)((float)t1 / Stopwatch.Frequency);}static double Test2(Dictionary<string, string> dict){var timer = new Stopwatch();timer.Start();var it = dict["2001"];var t1 = timer.ElapsedTicks;timer.Stop();return (float)((float)t1 / Stopwatch.Frequency);}#endregion#region 2018.7.7#region 數(shù)組的數(shù)組,二維數(shù)組static int[] returnArray(){//數(shù)組是引用類型,分配在堆上int[] arr = { 1, 2, 3, 4 }; //雖然這樣寫,其實(shí)等價于int[] arr = new int[]{1,2,3,4};return arr; //返回一個數(shù)組對象 }static void TestArray() {//1,一維數(shù)組char[] arr = new char[2] { 'a', 'b' }; //必須全部初始化,或不初始化int[] iarr = new int[2] { 0, 1 };char[] sarr = new char[3];//2,數(shù)組的數(shù)組,鋸齒數(shù)組char[][] d2arr = new char[2][];d2arr[0] = new char[30];d2arr[1] = new char[2] { 'a', 'b' };d2arr[0][1] = 'x';//3,二維數(shù)組,矩陣int[,] i2arr = new int[2, 3];for (var i = 0; i < 2; ++i){for (var j = 0; j < 3; ++j){i2arr[i, j] = i * 3 + j;}}}#endregion#region 字段初始化無法使用非靜態(tài)(字段、方法、屬性)delegate int mydelegate(int x);//-------------------------------------------------------------------------//字段初始化無法使用非靜態(tài)(字段、方法、屬性)//-------------------------------------------------------------------------float fxs;static float sfxs;//float fxs2 = fxs; //errorfloat fxs3 = sfxs; //right,可用靜態(tài)字段初始化float fxs4 = TestStaticInit(); //right,調(diào)用靜態(tài)函數(shù)初始化static int TestStaticInit() { return 10; }mydelegate _mydel = (x) =>//LINQ為什么可以?,從下面可知,LINQ語句只相當(dāng)于一堆初始化語句的集合 {//int fx = fxs; //errorreturn 20;};#endregion#region 默認(rèn)訪問修飾符//1,名字空間中,最外層類及接口的默認(rèn)修飾符為internal,也就是本程序集可訪問//2,類中,變量,成員,類中類的默認(rèn)修飾符為private//3,結(jié)構(gòu)中,同類//4,接口中,所有方法和屬性都為public,接口中只能有方法,不能有變量interface IMyinterface{//接口中可以有方法,抽象屬性,不可以有變量int Id { get; } //抽象屬性,公有void Fly(); //方法,公有 }#endregion#region 類模板繼承class CTClass<t1, t2, t3> //多個where的寫法where t1 : struct //必須是值類型where t2 : class //必須是引用類型where t3 : new() //必須有無參構(gòu)造函數(shù) {float fx, fy;public static t1 Add(t1 a, t1 b){return (dynamic)a + (dynamic)b;}}//模板繼承的幾種方式//1,全特化class CDTClass : CTClass<int, CCmpBase, CCmpBase> { }//2,原樣繼承,注意基類的所有約束都要重寫一遍class CDTX<t1, t2, t3, t4> : CTClass<t1, t2, t3>where t1 : struct //必須是值類型where t2 : class //必須是引用類型where t3 : new() //必須有無參構(gòu)造函數(shù) { }//3,偏特化,介于二者之間的形態(tài)#endregion#region 運(yùn)算符重載class CCmpBase{//帶有默認(rèn)構(gòu)造函數(shù)float _x;}class CComplex : CCmpBase{float real, image;public CComplex(float real, float image = 0){this.real = real;this.image = image;}//一,類型轉(zhuǎn)換 :數(shù)值轉(zhuǎn)對象//CComplex cp = 2.1f 或 CComplex cp; cp = 2.1f;//C#從不調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行類型轉(zhuǎn)換public static implicit operator CComplex(float real){return new CComplex(real);}//二,類型轉(zhuǎn)換:對象轉(zhuǎn)boolpublic static explicit operator bool(CComplex cp){return cp.real != 0 && cp.image != 0;}//三,類型轉(zhuǎn)換:對象轉(zhuǎn)數(shù)值public static implicit operator float(CComplex cp){return cp.real;}//四,算術(shù)運(yùn)算符重載 : +,-,*,/,%等//c#的運(yùn)算符重載全部為靜態(tài)函數(shù),因此沒有隱含參數(shù)//而C++運(yùn)算符重載時可以重載為友元,絕大多數(shù)重載為類的成員函數(shù),因此基本都有一個隱含參數(shù)(對象本身)public static CComplex operator +(CComplex a, CComplex b){return new CComplex(a.real + b.real, a.image + b.image);}public static CComplex operator ++(CComplex cp){cp.real++;cp.image++;return cp;}//五,不支持的運(yùn)算符重載//1,不允許重載=運(yùn)算符, C++可以,都不允許重載+=之類的//2,不允許重載括號()運(yùn)算符//3,不允許重載[]運(yùn)算符,因?yàn)樗撬饕?/span>//public static implicit operator () (CComplex cp)//{// return a;//}void TestPrivate(){var cp = new CComplex(1, 3);cp.real = 20;cp.image = 30.0f;}public void PrintInfo(){WriteLine("real:{0},image:{1}", real, image);}}static void TestOperatorOverload(){CComplex cp = new CComplex(1, 1);//1,同時支持前后向++,【不同于C++】cp++;++cp;//2,但不允許連++, 【不同于C++】//cp++++或 ++++cp cp.PrintInfo();//3,支持連續(xù)+,【同于C++】CComplex cp1 = new CComplex(1, 1);var cpadd = cp + cp1 + cp1 + cp1;cpadd.PrintInfo();//類型轉(zhuǎn)換運(yùn)算符cp = 2.1f;//類型轉(zhuǎn)換運(yùn)算符//C++中是調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù),而不是運(yùn)算符重載CComplex cp2 = 1.0f;}#endregion#endregion#region 2018.7.11#region 兩數(shù)相加函數(shù)模板實(shí)現(xiàn)static T MaxNum<T>(T a, T b){return ((dynamic)a > (dynamic)b) ? a : b;}#endregion#region thread lock//thread testclass Account{private object thisLock = new object();int balance;Random r = new Random();public Account(int initial){balance = initial;}int Withdraw(int amount){if (balance < 0){throw new Exception("Negative Balance");}lock (thisLock){if (balance > amount){WriteLine("before-withdraw: " + balance);WriteLine("amount to withdraw: " + amount);balance -= amount;WriteLine("after withdraw: " + balance);return amount;}elsereturn 0; //transaction rejected }}public void DoTransactions(){for (int i = 0; i < 100; ++i){Withdraw(r.Next(1, 100));}}}static void TestObjectLock(){Account acc = new Account(1000);Thread[] threads = new Thread[10];for (int i = 0; i < 10; ++i){threads[i] = new Thread(acc.DoTransactions);}for (int i = 0; i < 10; ++i){threads[i].Start();//threads[i].Join(); }}#endregion#region derive protectedclass A{float fxPrivate;protected int nProtected;protected A(int x) { }}class B : A //c++的公有繼承 {B(String name, int x) : base(x) { }protected int nProtected;void TestDerive(){//這里的規(guī)則與C++完全一樣://1,子類不能訪問基類的私有成員,可以訪問基類的保護(hù)和公有成員//2,保護(hù)成員可以在本類中訪問(不一定是本對象中)nProtected = 20;base.nProtected = 10;var ob = new B("b", 1);ob.nProtected = 30; //類中訪問類的保護(hù)成員,但不是本對象的成員 }}#endregion#endregion#region 2018.7.12#region 常量和靜態(tài)變量靜態(tài)類readonly//----------------------------------------------------------------------//常量和靜態(tài)變量,靜態(tài)類//----------------------------------------------------------------------//類的靜態(tài)變量和常量,都屬于類而不屬于對象,不能用對象來調(diào)用,只能用類名調(diào)用//這不同于C++,是更合理的設(shè)計//常量的值在類定義時就確定了,不因?qū)ο蠖煌?#xff0c;因此存放在類中更合理class CNormclass{class CInclass{public float fx = 20;}public int _id;public const string cname = "CNormalclass";//1,常量僅能修飾 :數(shù)字,bool,字符串,null引用//不能像C++那樣定義一個常量對象,這真是太悲哀了,因?yàn)楹芏鄷r候這可以加速數(shù)據(jù)傳遞,增加安全性//由于這個原因,C#的List.ToArray每次都只能返回一個內(nèi)部數(shù)組的拷貝,因此使用list存儲數(shù)量較大較復(fù)雜的數(shù)據(jù)時//不要輕易使用ToArray,直接用List就行了,它也支持下標(biāo)索引方式取數(shù)組元素const CInclass lst = null;//2,readonly也不能實(shí)現(xiàn)常量對象的效果//readonly僅表示變量本身不能被賦值,但不阻止通過對象變量更改對象內(nèi)的字段//onc.readonlyobj.fx = 20public float fx = 20;private readonly CInclass readonlyobj = new CInclass();public void FuncX() { }//3, 屬性不能用readonly修飾virtual public int ReadonlyProp {//4,屬性可以為虛private set; //可以加限定符get;}public static void Test(){//1,不能調(diào)用非靜態(tài)字段或方法//this._id = 20; //error,沒有this指針//2,可以調(diào)用常量字段var lname = cname;var onc = new CNormclass();//私有變量在類的靜態(tài)方法也可以訪問//2,雖然不能更改readonlyobj本身的值,卻可以更改其內(nèi)部成員的值,這就是readonly的作用onc.readonlyobj.fx = 20; }}static class C712//類中類,默認(rèn)為私有{//靜態(tài)類不能實(shí)例化,且只能聲明:常量,靜態(tài)常量,靜態(tài)屬性,靜態(tài)方法public const int constX = 20; //1,常量public static int staticX = 0; //2,靜態(tài)常量public static int ix { set; get; } //3,靜態(tài)屬性//一,【靜態(tài)類中不能定義實(shí)例化字段】//public int _id; //二,【靜態(tài)類中不能定義實(shí)例化字段】//void Ctest(){ //【error: 靜態(tài)類中不能定義實(shí)例化方法】// this._id = 20;//}static void Test()//4,靜態(tài)方法 {//三,【靜態(tài)方法中不能調(diào)用非靜態(tài)變量或方法,因?yàn)闆]有this指針】//_id = 20; //error //四,【可以調(diào)用常量字段,這與C++不同】var c = constX;}}public const int ixd = 20;public static float fx = 20;public void Testff(){fx = 30; //等價于Program.fx = 30,而不是 this.fx = 30;Program.fx = 30;var tx = C712.constX;C712.staticX = 30;var ix = Program.ixd;//var oc7 = new C712(); //error 靜態(tài)類不能創(chuàng)建實(shí)例 }#endregion#region 事件和委托//--------------------------------------------------------------//event -test//--------------------------------------------------------------//使用event的好處,與delegate的區(qū)別://event 本質(zhì)上是一個委托,是做了一些安全措施的委托//1,event 定義的委托只允許 +=操作,不允許=賦值,這樣防止事件被誤清空,delegate則沒有這些限制//2,event 定義的委托只能在本類中調(diào)用,可以防止外部觸發(fā),delegate沒有這些限制//3,不使用事件,delegate方式完全可以實(shí)現(xiàn)類似限制,通過私有變量和公有函數(shù)結(jié)合方式class EventTest{public delegate void Delx(string s = "");Delx _delegate; // 私有委托,防止外部調(diào)用public event Delx _event; //公有事件,給外部通過+=注冊使用,但_event()函數(shù)只能在本類調(diào)用,不能在類外調(diào)用//-------------------------------------------------------------//1 ,委托方式//-------------------------------------------------------------//(1)外部調(diào)用eventTest.AddListener(func)方式注冊事件public void AddListener(Delx callback){_delegate += callback;}//(2)本類對象調(diào)用此函數(shù)觸發(fā)事件void DelegateBrocast(){_delegate("delegate"); //回調(diào),觸發(fā)事件 }//-------------------------------------------------------------//2,事件方式//-------------------------------------------------------------//(1)外部使用 _event += 方式注冊回調(diào)函數(shù)//(2)本類對象調(diào)用此函數(shù)觸發(fā)事件void EventBrocast(){_event("event");//回調(diào),觸發(fā)事件 }}class Listener{public void OnEvent(string s){WriteLine("on-event---------------" + s);}}static void TestEventAndDelegate(){Listener l1 = new Listener();EventTest test = new EventTest();//1,事件方式test._event += l1.OnEvent; //注冊事件//test._event = l1.OnEvent; //編譯錯誤,事件只能使用+=,防止事件被清空//test._event("event"); //編譯錯誤,事件不能在類外調(diào)用,事件只能由其所在類調(diào)用//2,委托方式test.AddListener(l1.OnEvent); //注冊委托,通過函數(shù)對委托進(jìn)行注冊,因委托是私有的,可防止直接操作 test._delegate() }#endregion#region 文件和目錄static void FileAndDirectory(){//-------------------------------------------------------------------------//文件對象的相關(guān)操作//-------------------------------------------------------------------------//方式一,使用工具類:File類,不需生成對象var file = File.Open("f:/test.txt", FileMode.Create, FileAccess.ReadWrite);//方式二,通過FileStream的對象var filestream = new FileStream("f:/test._txt", FileMode.Create, FileAccess.ReadWrite);//-------------------------------------------------------------------------//目錄文件相關(guān)操作//-------------------------------------------------------------------------//方式一,實(shí)例化DirectoryInfo類var dir = new DirectoryInfo("f:/tolua");//(1)獲取目錄foreach (var d in dir.GetDirectories("*.*", SearchOption.AllDirectories)){WriteLine(d.FullName);}//(2)獲取文件foreach (var fileinfo in dir.GetFiles("*.*", SearchOption.AllDirectories)){WriteLine(fileinfo.FullName);}//方式二,使用工具類: Directory類,不需生成對象//(1)獲取目錄var dirs = Directory.GetDirectories("f:/tolua", "*.*", SearchOption.AllDirectories);//(2)獲取文件dirs = Directory.GetFiles("f:/tolua", "*.*", SearchOption.AllDirectories);for (int i = 0; i < dirs.Length; ++i){//打印輸出 WriteLine(dirs[i]);}}#endregion#endregion#region 2018.7.17#region 計算機(jī)中浮點(diǎn)數(shù)的存儲static void TestFloat(){using (var ms = new MemoryStream()){using (var br = new BinaryWriter(ms)){br.Write(125.5f);var bytes = ms.GetBuffer();}}unsafe{float fx = 125.5f;int* pfx = (int*)(&fx);}}#endregion#region 位移運(yùn)算static void TestBitShift(){ //----------------------------------------------------------------------------//十進(jìn)制數(shù)轉(zhuǎn)二進(jìn)制://1,原理:將數(shù)X右移1位,最低位被移出,再左移,得到了數(shù)X0,則x-x0即為最低位的值//2,手工算法:根據(jù)1的原理,不斷的對一個數(shù)整除2得余數(shù),了終得到余數(shù)序列即是二進(jìn)制的反向序列//3,左移等價于乘2,右移等價于除2,原理是乘法的豎式算法,// 101//x 010//------- 豎式算法適用于任何進(jìn)制的加減法和乘法運(yùn)算// 000//+101//-------// 1010//----------------------------------------------------------------------------int x = 7;List<Byte> bits = new List<Byte>(4);while (x != 0){var left = x - ((x >> 1) << 1);//<=> x - x/2*2bits.Add((byte)left);x = x >> 1;}}#endregion#region IEnumerableAndLinQclass Product{public int cateId;public string name;}class Category{public int id;public string name;}public static void TestIEnumerableAndLinq(){Category[] cates = new Category[]{new Category{id = 1, name = "水果"},new Category{id = 2, name = "飲料"},new Category{id = 3, name = "糕點(diǎn)"},};Product[] products = new Product[]{new Product{cateId=1, name = "apple"},new Product{cateId=1, name = "banana"},new Product{cateId=1, name = "pear/梨"},new Product{cateId=1, name = "grape/葡萄"},new Product{cateId=1, name = "pineapple/菠蘿"},new Product{cateId=1, name = "watermelon/西瓜"},new Product{cateId=1, name = "lemon/檸檬"},new Product{cateId=1, name = "mango/芒果"},new Product{cateId=1, name = "strawberry/草莓"},new Product{cateId=2, name = "bear/啤酒"},new Product{cateId=2, name = "wine"},new Product{cateId=3, name = "cake"},new Product{cateId=3, name = "basicuit/餅干"},};var rets = cates.Where((x) => { return x.id > 1 && x.id < 5; });var iter = rets.GetEnumerator();while (iter.MoveNext()){//WriteLine(iter.Current); }var set = from c in cates//這里只能寫一個條件,就是equals,用來關(guān)聯(lián)兩個表//并且 c相關(guān)的條件只能寫在equals左邊,p相關(guān)條件只能寫equals右邊join p in products on c.id equals p.cateId//這里存放的是 products中的元素合集,而不是cates中的元素合集//如果 from p in products join c in cates on c.id equals p.id into xgroups//則xgroups中放的是cates中的元素集合//這里是說將products中cateId等于c.id的所有元素放入一個組xgroups中 into xgroupsorderby c.id descending //對set中的結(jié)果進(jìn)行降序排列//where m > 4 && m < 10 //這里就可以寫多個條件了//from in 相當(dāng)于外層循環(huán),join in 相當(dāng)于內(nèi)層循環(huán)//select在雙層循環(huán)體中,每執(zhí)行一次循環(huán),【如果符合條件】,則執(zhí)行一次結(jié)果選擇//雙層循環(huán)完成后,最終將很多條選擇提交給set//【注意,如果不符合條件 select不會執(zhí)行】select new { cate = c.name, grp = xgroups }; //可以生成一個新的對象foreach (var p in set){WriteLine("分組:" + p.cate);foreach (var g in p.grp){WriteLine(g.cateId + "," + g.name);}}}#endregion#region 類和繼承class CTestX{public virtual void OnUpdate(){Console.WriteLine("base-on-update");}public virtual void OnUpdate2(){Console.WriteLine("base-on-update2");}public void Update(){this.OnUpdate(); //注釋1,如果子類有overide則調(diào)用子類的,否則調(diào)用自己的 }public CTestX(){}protected CTestX(float fx){WriteLine("CTestX");}~CTestX(){WriteLine("~Ctestx");}public float fx;string name;}//子類不能訪問基類任何私有的東西,包括方法,字段,屬性,但它們都被繼承了,屬于子類,從實(shí)例內(nèi)存可證//方法包括構(gòu)造函數(shù),即當(dāng)基類是私有構(gòu)造函數(shù)時,子類無法在初始化列表中調(diào)用base()來初始化class CTestChildX : CTestX{CTestX otestx;public CTestChildX() : base(1)//當(dāng)基類為私有構(gòu)造時,這里base無法調(diào)用{//當(dāng)基類沒有無參構(gòu)造函數(shù)時,必須在初始化列表中初始化所有成員對象,如otestxWriteLine("CTestChildX");}//注意overide與virtual的區(qū)別://1,overide : 表明【函數(shù)是對基類的重寫】 且 【本身是虛函數(shù)可被子類重寫】//【函數(shù)會與基類、子類發(fā)生虛函數(shù)機(jī)制】//2,virtual : 僅表明函數(shù)是個虛函數(shù),不會與基類發(fā)生虛函數(shù)機(jī)制//如果子類overide了該函數(shù),則會與子類發(fā)生虛函數(shù)機(jī)制//3,多級繼承中只要有一級沒override,虛函數(shù)機(jī)制就會打斷在此層級,見//override在編譯層的機(jī)制是重寫虛函數(shù)表中的函數(shù)地址//即將繼承而來的虛函數(shù)表中的虛函數(shù)地址替換成本類的虛函數(shù)地址public static void TestDerive(){// CTestX ox = new CTestChildX();// ox.OnUpdate(); //base-on-update,無虛函數(shù)機(jī)制發(fā)生// ox.OnUpdate2(); //child-on-update2,虛函數(shù)機(jī)制發(fā)生// ox = new CTestY();// ox.OnUpdate(); //base-on-update,無虛函數(shù)機(jī)制發(fā)生CTestChildX ocx = new CTestZ();ocx.OnUpdate(); //grand-child-on-update }public override void OnUpdate(){Console.WriteLine("child-on-update");}public override void OnUpdate2(){Console.WriteLine("child-on-update2");}~CTestChildX() //不支持virtual {WriteLine("~CTestChildX");}}class CTestY : CTestChildX{public override void OnUpdate(){Console.WriteLine("grand-child-on-update");}}class CTestZ : CTestY{//因?yàn)檫@里的Update不是虛函數(shù),因此public void OnUpdate(){Console.WriteLine("grand-grand-child-on-update");}}struct CTX{void Test() {//不支持C++的const語法 }}//1,不能繼承結(jié)構(gòu),可以實(shí)現(xiàn)接口,//2,不能有虛函數(shù)struct CCTX //: CTX {public void Test(){}}#endregion#region 字符串格式化static void TestStrFormat(){var str = Console.ReadLine();while (str != "exit"){int ix;Int32.TryParse(str, out ix); //ix = 120var f1 = string.Format("{0 :d5}", ix); //"00120"var f2 = string.Format("{0,-10:d5}", ix);//"00120 "var f3 = string.Format("{0:x}", ix); //16進(jìn)制輸出到字符串var f4 = string.Format("{0:0.000}", ix);//浮點(diǎn)數(shù) 120.000Console.WriteLine("-----------begin-------------");Console.WriteLine(f1);Console.WriteLine(f2);Console.WriteLine(f3);Console.WriteLine(f4);Console.WriteLine("------------end-------------");str = Console.ReadLine();}}#endregion#endregion#region 2018.7.25#region 引用返回值(不是右值引用)static int[] _bookNum = new int[] { 1, 2, 3, 4, 5, 6 };static ref int GetBookNumber(int i){int x = 10;return ref _bookNum[i];}static void TestRefReturn(){ref int rfn = ref GetBookNumber(1);rfn = 10101; //_bookNum[1]變成了 10101int vn = GetBookNumber(2);vn = 202; //_bookNum[2]未變,仍為3ref int x = ref vn;}#endregion#region 索引器class mylist<T>{const int defaultCap = 4;T[] items;int count;int cap = defaultCap;public mylist(int cap = defaultCap){if (cap != defaultCap)this.cap = cap;items = new T[cap];}public T this[int idx] {set {items[idx] = value;}get {return items[idx];}}}enum Color{red,green,blue,yellow,cyan,purple,black,white,}static void TestIndexer(Color clr = Color.black){mylist<string> lst = new mylist<string>();lst[1] = "hello";}#endregion#region 部分類//部分類的作用是可以把一個龐大的類拆分到多個文件,每個文件實(shí)現(xiàn)一部分//而不是實(shí)現(xiàn)像C++那樣將聲明與實(shí)現(xiàn)分開//若要實(shí)現(xiàn)聲明(接口)與實(shí)現(xiàn)分開,應(yīng)該使用抽象類或接口partial class CPartclass{public void ShowName() {WriteLine("show name");}}partial class CPartclass{public void ShowAge(){WriteLine("show age");}}static void TestPartclass(){CPartclass opc = new CPartclass();opc.ShowName();opc.ShowAge();}#endregion#region 動態(tài)分配對象數(shù)組C#與C++的區(qū)別struct xobject {public float fx, fy, fz; //全是public的 }static void TestDynamicAllocInCSharpCpp(){//1,對于引用類型數(shù)組,需要兩步才能完成,因?yàn)閿?shù)組中存放的是對象的引用//1.1 c#中xobject[] arr = new xobject[2];//這時候,只是分配了一個引用數(shù)組,arr[0],arr[1]均為nullfor (int i = 0; i < 2 ; i++){arr[i] = new xobject(); //為數(shù)組中每個引用申請對象 }//1.2 c++中//xobject** pp = new xobject*[2];//pp[0] = new xobject();//pp[1] = new xobject();//2 對于值類型數(shù)組,則只需一步,因?yàn)閿?shù)組中放的就是值,這在C#與CPP中都一樣//2.1 C#中int[] iarr = new int[2];var a0 = iarr[0]; //0var a1 = iarr[1]; //0 xobject[] varr = new xobject[3];varr[0].fx = 0.1f;varr[1].fy = 2.5f;varr[2].fz = 12;//2.2,在C++中//xobject* pobjs = new xobject[2]; //每個數(shù)組元素都是一個值類型對象//pobjs[0].fx = 20; }#endregion#region Object?語法static void TestobjAsk(){object obj = "hello";WriteLine(obj?.ToString());//如果obj不為null則調(diào)用tostring }#endregion#region C#默認(rèn)字符編碼及系統(tǒng)默認(rèn)編碼//默認(rèn)編碼為unicode,字符串本身的編碼并不重要,字節(jié)讀寫時指定的編碼才重要,如下面的BinaryWriter//Encoding.Default是當(dāng)前系統(tǒng)的默認(rèn)編碼,并不是c#字符串的默認(rèn)編碼//Encoding.Default規(guī)則:漢字2字節(jié),其它1字節(jié)static void TestDefaultStrEncoding(){string str = "hdd好";using (var ms = new MemoryStream()){using (var br = new BinaryWriter(ms, Encoding.Default)){br.Write(str);var len = ms.Length-1;WriteLine(len);}}}#endregion#region 屬性attribute和反射class ReflectableClass{public float fx;public string str;//static const int x = 20; //這在C++中是可以的public void Printstr(string str, int idx){WriteLine(str + ":" + idx);}}static void TestReflect(){ReflectableClass ox = new ReflectableClass();Type t = typeof(ReflectableClass);//Type.GetType("ConsoleApplication1.Program.ReflectableClass");//ox.GetType();var tname = t.GetField("name");var tfx = t.GetField("fx");var func = t.GetMethod("Printstr", new Type[] {typeof(string),typeof(int) });func.Invoke(ox, new object[] { "helloworld", 1 });Type Ts = Type.GetType("System.String");var fs = Ts.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });var subs = fs.Invoke("hello world", new object[] { 1, 5 });WriteLine(subs);}static void TestAttribute(){}#endregion#endregion#region 2018.7.30#region 擴(kuò)展方法測試static void TestExtMethod(){ExtTargetCls oet = new ExtTargetCls();oet.methodExt(100);WriteLine(oet.sum);}#endregion#region 元組:同時傳遞多個不同類型參數(shù)//作用時,可以很方便的,高效的返回一組不同類型的值或?qū)ο?/span>//因?yàn)槭欠盒?#xff0c;所以高效//但是它最多只有8個參數(shù),也就是說不能當(dāng)作ArrayObject的替代品static void TestTuple(){Tuple<int, float> tupleFunx(){return new Tuple<int, float>(1, 2);}var tp = tupleFunx();WriteLine(tp.Item1);WriteLine(tp.Item2);}#endregion#region 數(shù)組排序:實(shí)現(xiàn)IComparable和傳遞排序函數(shù)//注意,List排序也是這樣的,因?yàn)樗旧砭褪且粋€數(shù)組class ComparableObj<T> : IComparable{public T elem;public ComparableObj(T fx){elem = fx;}public int CompareTo(object obj){var objc = (dynamic)(ComparableObj<T>)obj;if (elem == objc.elem)return 0;else if (elem < objc.elem)return -1;return 1;}}static void TestCompareableobj(){var rand = new Random();ComparableObj<float>[] arrf = new ComparableObj<float>[10];for (var i = 0; i < 10; ++i){arrf[i] = new ComparableObj<float>(rand.Next(1, 100));Write(arrf[i].elem + " ");}WriteLine();//方式一,實(shí)現(xiàn)了IComparable,用它來排序,升序 Array.Sort(arrf);foreach (var a in arrf){Write(a.elem + " ");}WriteLine();//方式二,傳遞一個排序函數(shù),使用它來排序,降序Array.Sort(arrf, (a, b) =>{if (a.elem == b.elem)return 0;else if (a.elem < b.elem)return 1;return -1;});foreach (var a in arrf){Write(a.elem + " ");}WriteLine();}#endregion#region 只讀集合void TestReadonlySet(){var lst = new List<int>();var rdlst = lst.AsReadOnly(); //生成一個包裝類,引用原來的lst,因此是高效的//rdlst[0] = 2; //error, read onlyvar llst = new LinkedList<int>();//這個才是鏈表,而list就像是c++的vector }#endregion#endregion#region 2018.7.31#region JSONvoid TestJson(){}#endregion#region CPP與CS間數(shù)據(jù)傳遞轉(zhuǎn)換#endregion#region 線程static void TestThread(){//Thread.Yield();Thread t1 = new Thread(() =>{int i = 0;while (i++ < 25){Thread.Sleep(300);WriteLine("T1>> " + i);}});Thread t2 = new Thread(() =>{//t1先執(zhí)行(<=1000毫秒),t2等待t1.Join(1000);//t1,t2同時執(zhí)行,若上一步t1已完成則不執(zhí)行int i = 0;while (i++ < 10){Thread.Sleep(300);WriteLine("T2>> " + i);}//若t1還活著,繼續(xù)執(zhí)行//t2是前臺線程,main函數(shù)會等待t2的結(jié)束 t1.Join();});t1.Start();t2.Start();t1.IsBackground = true;t2.IsBackground = true;//t1.IsBackground = true;//t2.Join();Thread.Sleep(2000);WriteLine("main-thread-end");}#endregion#region 線程池void TestThreadPool(){}#endregion#region 任務(wù)static void TestTask(){WriteLine("TestTask: " + Thread.CurrentThread.ManagedThreadId);//任務(wù)開啟方式一,實(shí)例實(shí)現(xiàn)var task = new Task(() =>{WriteLine("task: " + Task.CurrentId + "," + Thread.CurrentThread.ManagedThreadId);});task.Start();task.Wait(); //等待方式一Task.WaitAny(task); //等待方式二//任務(wù)開啟方式二,靜態(tài)方法實(shí)現(xiàn)var t1 = Task<string>.Run(delegate //Task<string>中的string表示返回值類型,也可不寫,由模板自動推導(dǎo) {WriteLine("task1: " + Task.CurrentId + "," + Thread.CurrentThread.ManagedThreadId);Thread.Sleep(2000);return "suceed"; //返回值類型,對應(yīng)Task<string>中的string,如果類型寫錯也沒關(guān)系 });t1.Wait(); //等待任務(wù)完成,因?yàn)槭窃谥骶€程中調(diào)用的,因此是讓主線程等待任務(wù)完成,不寫的話主線程直接結(jié)束了WriteLine("線程1執(zhí)行結(jié)果:" + t1.Result); //suceed }#endregion#region 程序集#endregion#region 多線程調(diào)試#endregion#region 委托綜合使用小例子static void delegateTestx0 (){void ifunc(int x, Func<int, int> dx){WriteLine(dx(2));}var lst = new List<int>() { 1, 2, 3 };foreach (var v in lst){ifunc(1, delegate (int x) {//像lua的回調(diào)函數(shù)那樣使用return v; //閉包中的v });ifunc(1, (x) => { return v; });}}#endregion#region 異步 async awaitpublic static async void AsyncFunc(){WriteLine(Thread.CurrentThread.ManagedThreadId); //主線程var task = Task.Run(() =>{for(int i= 0; i<10; ++i){WriteLine(Thread.CurrentThread.ManagedThreadId + ":task>>" + i); //線程1Thread.Sleep(100);}});var task1 = Task.Run(() =>{for (int i = 0; i < 10; ++i){WriteLine(Thread.CurrentThread.ManagedThreadId + ":task1>>" + i);//線程2Thread.Sleep(100);}});await task; //等待線程1完成await task1;//等待線程2完成WriteLine("task and task1 finished");var task2 = Task.Run(() =>{for (int i = 0; i < 10; ++i){WriteLine(Thread.CurrentThread.ManagedThreadId + ":task2>>" + i);//線程3Thread.Sleep(100);}});await task2;//等待線程3完成Task.WaitAll(task, task1, task2); //無效,因?yàn)榇a執(zhí)行到這里時主線程已結(jié)束WriteLine("---------------------------------------------------");}public static void AsyncFunc2(){WriteLine(Thread.CurrentThread.ManagedThreadId); //主線程var task = Task.Run(() =>{for (int i = 0; i < 10; ++i){WriteLine(Thread.CurrentThread.ManagedThreadId + ":task>>" + i); //線程1Thread.Sleep(100);}});var task1 = Task.Run(() =>{for (int i = 0; i < 10; ++i){WriteLine(Thread.CurrentThread.ManagedThreadId + ":task1>>" + i);//線程2Thread.Sleep(100);}});task.Wait();//等待線程1完成task1.Wait();//等待線程2完成WriteLine("task and task1 finished");var task2 = Task.Run(() =>{for (int i = 0; i < 10; ++i){WriteLine(Thread.CurrentThread.ManagedThreadId + ":task2>>" + i);//線程3Thread.Sleep(100);}});task2.Wait();//等待線程3完成WriteLine("---------------------------------------------------");}//-----------------------------------------------------------------------//異步方式實(shí)現(xiàn)多個任務(wù)(線程)間的并發(fā)執(zhí)行與順序執(zhí)行//一個任務(wù)就是一個線程//await task 與task.wait的區(qū)別://task.wait會阻住當(dāng)前線程,直到task執(zhí)行完成,而await不會,它只表明了當(dāng)前在任務(wù)會在task之后執(zhí)行//-----------------------------------------------------------------------//方式一,采用 async-await方式實(shí)現(xiàn)//這種方式寫起來較優(yōu)雅,但較抽象,且不知道所有任務(wù)的結(jié)束點(diǎn),Task.waitAll對此無效static void TestAsyncAwait(){WriteLine(Thread.CurrentThread.ManagedThreadId); //主線程 AsyncFunc();WriteLine("after asyncfunc");//必須這樣等待任務(wù)結(jié)束,因?yàn)锳syncFunc中的Task.WaitAll無效//或者將每個任務(wù)都設(shè)置為前臺線程Thread.Sleep(3000); }//方式一,采用不使用 async-await關(guān)鍵詞,直接使用Task的基本功能來實(shí)現(xiàn)//這種方式更直觀,易于理解,且利于控制static void TestAsyncWait(){WriteLine(Thread.CurrentThread.ManagedThreadId); //主線程var task = Task.Run((Action)AsyncFunc2);WriteLine("after asyncfunc");task.Wait();}#endregion#region 正則表達(dá)式#region 貪婪匹配和最少匹配#endregion #region 分組 #endregion#endregion#region 正則在字符串中的使用static void TestRegexInStr(){var st = "hello;world;a";var mt = Regex.Match(st, ";world;");var ret = mt.Result(".");//???// string pattern = "--(.+?)--"; // string replacement = "($1)"; // string input = "He said--decisively--that the time--whatever time it was--had come."; // foreach (Match match in Regex.Matches(input, pattern)) // { // string result = match.Result(replacement); // Console.WriteLine(result); // } }#endregion#endregion#region 2018.8.1#region 異步調(diào)用Invokedelegate void MyTakeAwhileDelegate(int x, int time);static MyTakeAwhileDelegate a = invokefunc;static void invokefunc(int x, int time){WriteLine("begin invoke: " + Thread.CurrentThread.ManagedThreadId);//var str = Console.ReadLine();//WriteLine(">>" + str); Thread.Sleep(time);}static void TestInvoke(){// var iar = a.BeginInvoke(delegate(IAsyncResult ar) {// WriteLine("complete: " + ar.IsCompleted);// WriteLine("end invoke: " + Thread.CurrentThread.ManagedThreadId);// TestInvoke();// // }, null);//【線程的順序執(zhí)行模式】//多個線程對同一函數(shù)進(jìn)行順序訪問,不需要考慮線程同步問題,也不需要waitone等操作//不管系統(tǒng)會使用多少個線程來處理工作,但同時只有一個在執(zhí)行,EndInvoke保證了這一點(diǎn)//這種模式在網(wǎng)游客戶端中很有用,客戶端只需要2個線程:一個主線程用于處理游戲邏輯與顯示畫面//另一個線程則用于與后端進(jìn)行網(wǎng)絡(luò)通訊,這個線程就只需要使用【線程的順序執(zhí)行模式】//來循環(huán)處理網(wǎng)絡(luò)消息:讀取網(wǎng)絡(luò)消息,阻塞等待讀取完成,然后再讀取網(wǎng)絡(luò)消息,阻塞等待讀取完成...while (true){//注意這里的參數(shù)與委托對應(yīng),而且多了兩個:callback, obj是系統(tǒng)加的var ar = a.BeginInvoke(1, 1000, null, null);a.EndInvoke(ar); //阻塞,只到線程執(zhí)行完線程函數(shù) }//a.EndInvoke(iar);//iar.AsyncWaitHandle.WaitOne(); }#endregion#region 初始化器class CInitclass{public CInitclass() { }public CInitclass(string name, int age){this.name = name; this.age = age;}public string name;public int age;}static void TestInitial(){var oc = new CInitclass { name = "jim", age = 14 };var oc1 = new CInitclass() { name = "jim", age = 14 };var oc2 = new CInitclass("tim", 13) { name = "jim", age = 14 };var oc3 = new { name = "jim", age = 14, sex = 1 }; //匿名對象int[] arr = { 1, 2, 3 };int[] arr2 = new int[] { 1, 2, 3 };List<int> lst = new List<int> { 1, 2, 3 };List<int> lst1 = new List<int>(10) { 1, 2, 3 }; //capacity = 10lst1.Capacity = 5;WriteLine(lst1.Capacity);lst1.ForEach((i) => WriteLine(i));var dict = new Dictionary<int, string> { { 1, "a" }, { 2, "b" }, { 3, "c" } };var dict1 = new Dictionary<int, string>() { { 1, "a" }, { 2, "b" }, { 3, "c" } };}#endregion#region 協(xié)變和逆變//協(xié)變發(fā)生在數(shù)組,模板,委托上,//父子類之間的轉(zhuǎn)換不是協(xié)變,不是逆變//轉(zhuǎn)變的前提是元素類型有父子關(guān)系,如 class A{}; class B : A{}; B b; A a;//若子群可以轉(zhuǎn)為父群,則稱為協(xié)變,如 A[] a = new B[10]//協(xié)變必須是在引用類型之間,值與引用類型之間是不能協(xié)變的,如 object[]和 int[]//雖然 object是int的父類,但 int 是值類型//再如 object[] strs = new string[10]是可以的,因?yàn)?object就string的父類且二者都是引用類型//======================================================================//總結(jié):協(xié)變和逆變只是父子對象間轉(zhuǎn)換規(guī)則在模板,委托,數(shù)組上的表現(xiàn)//本質(zhì)上還是子對象轉(zhuǎn)父對象,沒有父對象轉(zhuǎn)子對象的現(xiàn)象存在//模板類中的協(xié)變與逆變轉(zhuǎn)換過程較為抽象,難時一眼看出,解析方法是:用實(shí)際生成的對象去調(diào)用,在調(diào)用過程中分析//如下面的二例:【泛型委托中的協(xié)變逆變】和【泛型接口中的協(xié)變逆變】#region 普通協(xié)變逆變class tshape<T> { }class tcircle<T> : tshape<T> { }static void xiebianx(CTestX[] array){array = new CTestChildX[10];}static void TestXiebianNibian(){object[] ocs = new CNormclass[10];object[] strs = new string[10];//協(xié)變的一個陷阱,編譯時正常,運(yùn)行時拋出異常: 類型不匹配strs[0] = 10;//泛型類本身的協(xié)變(有父子關(guān)系,泛型參數(shù)相同)tshape<int>[] tsps = new tshape<int>[10];tshape<CNormclass>[] tcs = new tcircle<CNormclass>[10];//通過函數(shù)參數(shù)測試普通類的轉(zhuǎn)變CTestX[] ox = new CTestX[10];xiebianx(ox);}#endregion#region 委托中的協(xié)變逆變class XIEBIAN{delegate CTestX[] ArrDelegate();CTestChildX[] func001(){return new CTestChildX[10];}delegate CTestX JustDelegate();CTestChildX func002(){return new CTestChildX();}void TEst(){ArrDelegate ad = func001;JustDelegate dd = func002;}}#endregion#region 泛型委托中的協(xié)變逆變delegate void FuncPtrin<in T>(T ox);//這里的in僅用來限制T類型,說明T只可用于輸入?yún)?shù),而不能用于輸出。in與協(xié)變逆變無關(guān)。可以去除void testfuncptr1(CTestX ox){}delegate T FuncPtrout<out T>();//out限制T只能用于輸出參數(shù),即返回值。與協(xié)變逆變無關(guān)。可去除 CTestX testfuncptr2(){return new CTestChildX();}void testfuncptr(){//泛型委托的協(xié)變比較抽象,其實(shí),從它的【調(diào)用原理】來思考就很容易了FuncPtrin<CTestChildX> p1 = testfuncptr1;FuncPtrin<CTestX> p2 = testfuncptr1;//【調(diào)用原理】://1,p1的實(shí)參必須是T類型//2,p1的實(shí)參必須能傳入它指向的函數(shù)中p1(new CTestChildX());p2(new CTestChildX());p2(new CTestX());FuncPtrout<CTestX> p3 = testfuncptr2;CTestX otx = p3();//-----------------------------------------------------------------------//其實(shí)這里不存在什么所謂的逆變,只有一種規(guī)則:子對象可以轉(zhuǎn)為父對象//只要讓參數(shù)接收者和返回值接收者都是父對象,就可以了//----------------------------------------------------------------------- }#endregion#region 泛型接口中的協(xié)變逆變class CAnimal {}class CDog : CAnimal{}interface ISpeak<in T, out T2>//這里的in和out就是協(xié)變逆變的關(guān)鍵了,沒有它們編譯器不知道如何進(jìn)行父子關(guān)系轉(zhuǎn)換 {T2 PrintInfo(T o);float fx { set; get; }}class Speaker<T, T2> : ISpeak<T, T2>where T2 : new() //必須有公有無參構(gòu)造函數(shù)(或默認(rèn)構(gòu)造函數(shù)) {public float fx { set; get; }public T2 PrintInfo(T o){return new T2();}}void Test003(){ISpeak<CDog, CAnimal> speaker = new Speaker<CAnimal, CDog>();speaker.PrintInfo(new CDog());}#endregion#endregion#region 2018.8.2#region 相等比較static void TestVarEquals(){//--------------------------------------------------------------//C#中字符串都是常量,但在底層實(shí)現(xiàn)上還是C++的方式,分為常量字符串與變量字符串//1,以數(shù)組形式給出的字符串是變量字符串//2,以字符串形式給出的是常量字符串//每個變量字符串都有不同的地址,而一個常量字符串只有一個地址,它是全局的//如下sa, sb指向兩個地址不同而內(nèi)容相同的字符串,sa1,sb1都指向同一個常量字符串"hello"string sa = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); //變量字符串string sb = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });//變量字符串string sa1 = "hello";//常量字符串string sb1 = "hello";//常量字符串WriteLine(sa.GetHashCode() + "," + sb.GetHashCode());WriteLine(sa.Equals(sb));//true,調(diào)用string.equals(string)WriteLine(sa == sb);//true,string的operator ==object oa = sa;object ob = sb;object oa1 = sa1;object ob1 = sb1;WriteLine(oa.Equals(ob));//true, 多態(tài)調(diào)用,實(shí)際調(diào)用的是string.Equals(object)WriteLine(oa1.Equals(ob1));//true, 多態(tài)調(diào)用,實(shí)際調(diào)用的是string.Equals(object)//運(yùn)行時,打印sa,sb, sa1, sb1的地址,可以看到sa,sb中存放的地址不同,sa1,sb1中存放的地址相同// &sa// 0x000000000028ecb0// * &sa: 0x0000000002472ed8// & sb// 0x000000000028eca8// * &sb: 0x0000000002472f70// & sa1// 0x000000000028eca0// * &sa1: 0x0000000002472dc0// & sb1// 0x000000000028ec98// * &sb1: 0x0000000002472dc0WriteLine("ref equal : " + ReferenceEquals(sa, sb));WriteLine("ref equal : " + ReferenceEquals(sa1, sb1));WriteLine("oa == ob: " + (oa == ob)); //false,oa,ob中存放的地址不同WriteLine("oa1==ob1: " + (oa1 == ob1)); //true,oa1,ob1中存放的地址相同,都是常量字符串hello的地址 object oc = new object();object od = new object();WriteLine(oc.Equals(od)); //false, object.equals(object)WriteLine(oc == od);//false//如果沒有實(shí)現(xiàn)重寫,對于引用類型,那么原始的object.equals()與 ==沒有任何區(qū)別,二者總能得到一樣的結(jié)果//因?yàn)橐妙愋推鋵?shí)是一個指針,==比較的是指針的值,也就是地址,equals比較的也是地址。//string類重寫了==和equals,實(shí)現(xiàn)了字符串內(nèi)容的比較,而非地址的比較。object o1 = new CNormclass();object o2 = new CNormclass();WriteLine(o1.Equals(o2)); //false, 多態(tài)調(diào)用, CDefOveride.Equals(object)int ia = 12;short isa = 12;WriteLine(ia.Equals(isa)); // true, short可以轉(zhuǎn)為int,故多態(tài)調(diào)用Int32.Equals(Int32 obj)WriteLine(isa.Equals(ia)); // false, int不能直接轉(zhuǎn)為short,故多態(tài)調(diào)用Int16.Equals(object obj) }#endregion#endregion#region 2018.8.3#region 線程同步#region 同步事件和等待句柄//https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/threading/thread-synchronizationstatic void TestWaitHandle(){//自動重置事件//一次只能激活一個線程,因?yàn)橐坏┘せ詈笮盘柋蛔詣又脼榱薴alsevar autoEvent = new AutoResetEvent(false);void tfunc(object o){WriteLine("worker thread " + (int)o + " started, now waiting on some event ... ");autoEvent.WaitOne();WriteLine("worker thread " + (int)o + " reactivated, now exiting...");}var threads = new Stack<Thread>();WriteLine("輸入創(chuàng)建 的線程數(shù)");var num = 1;while (!(int.TryParse(ReadLine(), out num))){}for(int i=0; i < num; ++i){var t = new Thread(tfunc);t.Start(i);threads.Push(t);Thread.Sleep(20);}Thread.Sleep(1000);while(threads.Count > 0){ReadKey();autoEvent.Set(); //發(fā)出信號,設(shè)置信號為true,一旦有線程被激活后,信息就被設(shè)置為了false threads.Pop();}}#endregion#region 一個線程終止另一個線程及信息傳遞異常捕獲class CThreadAbortInfo{public string info;public CThreadAbortInfo(string s){info = s;}}static void TestThreadAbort(){var t1 = new Thread(() =>{WriteLine("t1 started");try{int i = 0;while (true){Write(".");Thread.Sleep(200);i = i / 0;}}catch (DivideByZeroException e)//如果不處理,則系統(tǒng)會自己處理 {//throw; //讓程序引發(fā)異常,如果不寫,則程序正常運(yùn)行,因?yàn)楫惓1粊G棄了 }catch (ThreadAbortException ex)//如果不處理,程序正常運(yùn)行 {var info = ex.ExceptionState as CThreadAbortInfo;if (info != null){WriteLine(info.info);}}});t1.Start();var t2 = new Thread(() =>{Thread.Sleep(1000);//調(diào)用這個函數(shù),會拋出異常,但若不去捕獲,程序就什么都不會發(fā)生//拋出異常與顯示異常是不同的t1.Abort(new CThreadAbortInfo("t1 is terminated by thread t2"));});t2.Start();}#endregion#endregion#region as和引用類型轉(zhuǎn)換本質(zhì)void Refcasttype(){//注意,不論是as轉(zhuǎn)換還是強(qiáng)制轉(zhuǎn)換都是在指針轉(zhuǎn)換,而不是對象轉(zhuǎn)換,遵守C++的規(guī)則:子類可以轉(zhuǎn)父類//C#中,父類也可以轉(zhuǎn)子類,因?yàn)樗鼈兌际侵羔?#xff0c;但若實(shí)際類型不符合則結(jié)果為空var o = new CNormclass();var t = o as IDisposable;var ot = new CTestX();var ot2 = new CTestChildX();WriteLine("as1: " + ((CTestChildX)ot));WriteLine("as1: " + (ot as CTestChildX));WriteLine("as3: " + (ot2 as CTestX));WriteLine("as4: " + ((CTestChildX)ot2));using (ot as IDisposable)//判斷如果它實(shí)現(xiàn)了該接口 {}}#endregion#region 多播委托delegate void MDX();static void TestMultiDelegate(){void func1(){WriteLine("func1");}void func2(){WriteLine("func2");}void func3(){WriteLine("func3");}MDX md = func1; //【!】第一步不能寫 +=,因?yàn)樗€沒有初始值md += func3;md += func2;md(); //func1 func3 func2 執(zhí)行順序與添加順序相同md -= func1;md(); //func3 func2//md -= (func2 + func3); //wrongmd = func1; //ok,事件不允許這樣 md();md -= func1; //編譯運(yùn)行都OK,調(diào)用出錯md -= func2; //編譯運(yùn)行都OK,調(diào)用出錯md();//調(diào)用異常 }#endregion#region UDP通信static void TestUDp(){var ipenda = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);var ipendb = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12000);void StartUdpClientA(){UdpClient udp = new UdpClient(ipenda);//udp.Connect(ipendb);while (true){var recvBytes = udp.Receive(ref ipendb);var bytes = Encoding.ASCII.GetBytes("信息已收到[" + recvBytes.Length + "],請繼續(xù)發(fā)送");Thread.Sleep(1000);udp.Send(bytes, bytes.Length, ipendb);}}void StartUdpClientB(){UdpClient udp = new UdpClient(ipendb);//udp.Connect(ipend);while (true){WriteLine("請輸入發(fā)信息:");var str = ReadLine();var bytes = Encoding.ASCII.GetBytes(str);udp.Send(bytes, bytes.Length, ipenda);WriteLine("信息已發(fā)送等待回復(fù):");var recvBytes = udp.Receive(ref ipenda);WriteLine(">>收到回復(fù),字節(jié)數(shù):" + recvBytes.Length);}}var t1 = new Thread(StartUdpClientA);var t2 = new Thread(StartUdpClientB);t1.Start();t2.Start();}#region TCP通信#endregion#endregion#region 可空類型void TestNullabletype(){//可空類型是一個泛型結(jié)構(gòu)體Nullable<int> ix0 = null;//等同于下式int? ix = null; //可空類型object oa = 5;int iy = ix ?? 7; //7object ob = oa ?? 10; //5 WriteLine(iy);WriteLine(ob);}#endregion#endregion#region 2018.8.4#region 抽象類與接口對比interface ixinterface//不能加sealed {//1, 接口中不能寫public,因?yàn)槟J(rèn)為public,C#不會存在可有可無的東西//2,接口可以有抽象int this[int x] { set;get; } //3,接口中不可以寫實(shí)例化字段和屬性//4,可以有事件 }abstract class AbstractClass//不能加sealed {//int this[int x] { set; get; }int ix { set; get; }public abstract int iy { set; get; }void Func() { }int this[int x] {//可以定義索引器,但必須實(shí)現(xiàn)set { }}}class Dabclass : AbstractClass{public override int iy { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }}#endregion#endregion#region C#的析構(gòu)函數(shù)不同于C++class myTemp<T>{public myTemp(){}/*private virtual */~myTemp(){//析構(gòu)函數(shù)不能帶任何限制聲明,如public, protected, private, }}class Tehua : myTemp<string>{}#endregion #region 2018.8.14static void testIntLimit(){var le = -2147483648 < 2147483648;int ix = -2147483648;WriteLine(ix - 1); //0x80000000 + 0xffffffff = 0x7fffffff } #endregion#endregion// ctrl + w, t 可以察看所有待做任務(wù)static void Main(string[] args){//TestVarEquals();//TestUDp();//TestWaitHandle();//TestThreadAbort();//TestMultiDelegate();//TestVarEquals();//TestInitial();//TestInvoke();//Thread.Sleep(30000);//TestXiebianNibian();//TestAsyncWait();//TestTask();//TestThread();//TestRegexInStr();//TestCompareableobj();//TestExtMethod();//TestReflect();//TestDefaultStrEncoding();//TestDynamicAllocInCSharpCpp();//TestPartclass();//TestRefReturn();//TestOperatorOverload();// CTestChildX.TestDerive();//TestFloat();//var arr = returnArray(); }}#region 擴(kuò)展方法sealed class ExtTargetCls{public float sum = 10;}//擴(kuò)展方法必須在頂級靜態(tài)類中定義,不能是內(nèi)部類//能不能通過擴(kuò)展方法來修改類庫以達(dá)到不法目的? 不能,因?yàn)閿U(kuò)展方法只能修改類的公有成員static class ExtentMethod{public static void methodExt(this ExtTargetCls target, float add){target.sum += add;}}#endregion}?
posted on 2018-08-14 11:25 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏
總結(jié)
以上是生活随笔為你收集整理的2018.8.14-C#复习笔记总的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2018.8.14-C++复习笔记总
- 下一篇: c# char unsigned_dll