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() { //一个流不能兼备读写两种操作,不知道为什么,这不合理 string s1 = "你好啊ABC"; var t = "你好啊ABC".Length; //关于编码注意几点: //1,sizeof(char) 等于 2 //2,str.Length 是以元素个数算的,不是按字节算的,如 "你好啊ABC” length = 6 //3,c#在VS的默认编码为 Encoding.Default, 该编码下汉字占两字节,非汉字占1字节,通过查看ms中的字节数据可知 //4,string 类型写入任何buffer时都是先写长度,一般为1字节,再写字节数据,如下 var sz = sizeof(char); //2, 注意char占2字节 var szb = sizeof(bool); //1 var 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个以上字节才能表示 //编码方式 //1,ASCII码,只有一个字节,不能正确表示汉字,出现乱码,可以正确表示数字和字母符号 //2,UNICODE,任何符号都用2个字节表示,因此可以表示汉字和任意符号 //3,UTF8,变字节的编码,可以正确表示任何字符和汉字,各国语言 //4,GB2312编码,国标码,主要是为汉字服务的中国编码,汉字占两字节,字母数字占1字节 //5,default编码,在国内, 般就是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 计算机中数据的存储 // static void TestTypeConvert() { //把一个有符号数转为无符号后再转回来值保持不变,以下以1字节为例 //原理:计算机中符点数都是有符号的,不存在这种转变,只剩下整数, //真值:绝对值的二进制值,如-1的真值为 00000001 //整数是以补码形式存放的,计算机规定了正数的补码是本身,负数的补码是:符号位不变,真值按位取反再加1 //强制转换做的事就是把一个补码看成是有符号还是无符号 //有符号数,在计算时:符号位不变,真值按位取反再加1。无符号数直接计算,举例如下: //1,-1 的真值为00000001,补码为 1 111 1111,强转时就是把补码值看作是一个无符数,因此它=255 //,再次强转时把它看成有符号数,符号位不管,其余位按位取反加1后是1,因此再次转回了-1 //2,-2 的真值为00000010,补码为 1 111 1110,强转时把补码看作无符号数,因此它=254 //3,-128真值有点特殊,128的二进制码为1000 0000,第8位是符号位,舍弃,取后面的0,即-128的真值为0 //补码经按位取反加1后还是 1 000 0000,强转时看成无符号数即为128 //------------------------------------------- //1字节数据和2字节数据进行加法运算时,要进行位扩展,将1字节扩展为2字节 //正数扩展时高位补0,负数扩展时高位补1 //C#中小于4字节的数据进行运算时会先扩展成int再进行 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 { //不被编译系统做编译时安全检查 } } 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("未发现字符串结束符"); 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的区别,如 s1="h0ello", s2 = "h\0ello" //s2中的\0是字符串结尾符,除了C#不把它作为结束符外,其它语言都把它作为结束符,如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) //通过下面的实测,发现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风格:指定初始化容量20,使用初始化列表给部分成员赋值 var lst = new List (20) { 1, 3, 4, 20, -2, 9, 0 }; for (var i = 0; i < lst.Count; ++i) { //使用下标进行随机访问,说明list不是一个真正的链表,而是类似STL的Vector Console.WriteLine(lst[i]); } //public void Sort (Comparison comparison) //public delegate int Comparison (T x, T y); //这是对调用List .Sort进行排序的写法,其中sort的定义及Comparison委托的定义如上 lst.Sort(new Comparison (delegate (float m1, float m2) //委托 { return 1; })); lst.Sort(delegate (float m1, float m2) //委托 { return 1; }); lst.Sort((float m1, float m2) =>//Linq表达式 { return 1; }); lst.Sort((m1, m2) => //Linq表达式 { return 1; }); } static string TestRetStr() { //测试返回字符串是否会复制 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();//输出结果:child,如果注释1处函数不加override,输出结果为:base var 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 template class myTemp //类入口 { public T1 Add(T1 a, T1 b) { //模板类型不能直接相加,必须先转为动态类型,避开编译检查,运行时动态决定类型 dynamic da = a; dynamic db = b; return da + db; } public void tint ()//注意C++不能这么写,所有模板参数必须由类入口传入 { Type t = typeof(T3); WriteLine(t); } } delegate void refOutFunc(ref double t1, out double t2); delegate T TemplateDelegate (T a, U b); static void TestRefAndOut() { //ref, out 本质上都是引用 //fef就为了传给函数使用,必须先初始化,但也可以传出数据,out是为了从函数中传出数据使用,不用初始化 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 (); otp.tint