C# 全总结

   1 using System;
   2 using System.Collections.Generic;
   3 //using System.Linq;
   4 using System.Text;
   5 using System.Diagnostics;
   6 using System.IO;
   7 using static System.Console;
   8 using System.Linq;
   9 using System.Runtime.InteropServices;
  10 using System.Threading;
  11 
  12 namespace ConsoleApplication1
  13 {
  14     class Program
  15     {
  16         [DllImport("dltest.dll", EntryPoint ="Print")]
  17         static extern void xPrint(int x);
  18         #region old-test
  19 
  20         //
  21         static void TestStreamReadWrite()
  22         {//一个流不能兼备读写两种操作,不知道为什么,这不合理
  23             string s1 = "你好啊ABC";
  24 
  25             var t = "你好啊ABC".Length;
  26             //关于编码注意几点:
  27             //1,sizeof(char) 等于 2
  28             //2,str.Length 是以元素个数算的,不是按字节算的,如 "你好啊ABC” length = 6
  29             //3,c#在VS的默认编码为 Encoding.Default, 该编码下汉字占两字节,非汉字占1字节,通过查看ms中的字节数据可知
  30             //4,string 类型写入任何buffer时都是先写长度,一般为1字节,再写字节数据,如下
  31             var sz = sizeof(char); //2, 注意char占2字节
  32             var szb = sizeof(bool); //1
  33 
  34             var ms = new MemoryStream();
  35             var writer = new BinaryWriter(ms, Encoding.UTF7);
  36             writer.Write(s1);
  37             ms.Close();
  38             writer.Close();
  39 
  40             var ms2 = new MemoryStream(ms.GetBuffer());
  41             var reader = new BinaryReader(ms2, Encoding.UTF8);
  42             var s2 = reader.ReadString();
  43 
  44         }
  45 
  46         //
  47         static void TestEncoding()
  48         {
  49             string s1 = "你好啊ABC";
  50 
  51             //汉字乱码问题,汉字必须使用2个以上字节才能表示
  52             //编码方式
  53             //1,ASCII码,只有一个字节,不能正确表示汉字,出现乱码,可以正确表示数字和字母符号
  54             //2,UNICODE,任何符号都用2个字节表示,因此可以表示汉字和任意符号
  55             //3,UTF8,变字节的编码,可以正确表示任何字符和汉字,各国语言
  56             //4,GB2312编码,国标码,主要是为汉字服务的中国编码,汉字占两字节,字母数字占1字节
  57             //5,default编码,在国内, 般就是GB2312
  58             Encoding.Default.GetBytes(s1);
  59             var bytes = Encoding.GetEncoding("GB2312").GetBytes(s1);
  60             var len = bytes.Length;
  61             var bts = new byte[10 + len];
  62             Array.ConstrainedCopy(bytes, 0, bts, 0, len);
  63 
  64             var s2 = Encoding.GetEncoding("GB2312").GetString(bts).TrimEnd('\0');
  65             string s3 = "\0hello/0/0dddddd".TrimStart('\0');//!!!!!!!!!!!!!!!!!!!!!!!!!!!!    
  66 
  67         }
  68 
  69         #region 计算机中数据的存储
  70         //
  71         static void TestTypeConvert()
  72         {//把一个有符号数转为无符号后再转回来值保持不变,以下以1字节为例
  73             //原理:计算机中符点数都是有符号的,不存在这种转变,只剩下整数,
  74             //真值:绝对值的二进制值,如-1的真值为 00000001
  75             //整数是以补码形式存放的,计算机规定了正数的补码是本身,负数的补码是:符号位不变,真值按位取反再加1
  76             //强制转换做的事就是把一个补码看成是有符号还是无符号
  77             //有符号数,在计算时:符号位不变,真值按位取反再加1。无符号数直接计算,举例如下:
  78             //1,-1 的真值为00000001,补码为 1 111 1111,强转时就是把补码值看作是一个无符数,因此它=255
  79             //,再次强转时把它看成有符号数,符号位不管,其余位按位取反加1后是1,因此再次转回了-1
  80             //2,-2 的真值为00000010,补码为 1 111 1110,强转时把补码看作无符号数,因此它=254
  81             //3,-128真值有点特殊,128的二进制码为1000 0000,第8位是符号位,舍弃,取后面的0,即-128的真值为0
  82             //补码经按位取反加1后还是 1 000 0000,强转时看成无符号数即为128
  83             //-------------------------------------------
  84             //1字节数据和2字节数据进行加法运算时,要进行位扩展,将1字节扩展为2字节
  85             //正数扩展时高位补0,负数扩展时高位补1
  86             //C#中小于4字节的数据进行运算时会先扩展成int再进行
  87             sbyte sb = -127;
  88             var b = (byte)(sb);
  89             var sb1 = (sbyte)(b);
  90             object dx = 10.0f;
  91             double dx2 = 33;
  92             byte ix = (byte)dx2;
  93 
  94             var t = dx.GetType();
  95             Type T = System.Type.GetType(t.FullName, true);
  96 
  97 
  98         }
  99         #endregion
 100 
 101         //
 102         void TestUncheck()
 103         {
 104             unchecked
 105             {//不被编译系统做编译时安全检查
 106 
 107             }
 108         }
 109 
 110         static void TestBoxing()
 111         {
 112             int i = 10;
 113             object o = 1;
 114             int i2 = (int)o;
 115         }
 116 
 117         static void TestReadBytes()
 118         {
 119             byte[] bts = new byte[4] { 23, 0, 16, 0 };
 120             var ms = new MemoryStream(bts);
 121             var br = new BinaryReader(ms);
 122             var p1 = ms.Position;
 123             var ix = br.ReadUInt32();
 124             var p2 = ms.Position;
 125             Console.WriteLine("num=" + ix);
 126             br.Dispose();
 127             br.Close();
 128             ms.Dispose();
 129             ms.Close();
 130         }
 131 
 132         static void TestStrEnd()
 133         {
 134             string str = "abcde\0";
 135             var br = new BinaryReader(new MemoryStream(Encoding.ASCII.GetBytes(str)));
 136             var b = br.ReadByte();
 137             while (b != 0)
 138             {
 139                 Console.WriteLine(b);
 140                 try
 141                 {
 142                     b = br.ReadByte();
 143                 }
 144                 catch (System.Exception ex)
 145                 {
 146                     Console.WriteLine("未发现字符串结束符");
 147                     break;
 148                 }
 149             }
 150         }
 151 
 152         static void TestBigEndia()
 153         {
 154             var br = new BinaryWriter(File.Create("f:/testx.dt"), Encoding.ASCII);
 155             br.Write((Int16)9);
 156             string str = "Stand";
 157             br.Write(str);
 158             br.Write((Int16)10);
 159             br.Write((Int16)70);
 160             br.Dispose();
 161 
 162         }
 163 
 164         static void TestChar0()
 165         {//注意字符串中0和\0的区别,如 s1="h0ello", s2 = "h\0ello"
 166             //s2中的\0是字符串结尾符,除了C#不把它作为结束符外,其它语言都把它作为结束符,如U3D,LUA,C/C++等
 167             //而s1中的0仅是一个字符0而已,字符0的ASCII值是0X31=49,'\0'的ASCII值是0
 168             //注意这两种0在C#和U3D的API之间切换时容易造成BUG,如:
 169             //1, debug.log(s1): "h0ello"
 170             //2,debug.log(s2): "h"
 171             var s = "hello";
 172             s += 0 + ",world";
 173             var s1 = "hello";
 174             s1 += (char)0 + ",world";
 175             var s2 = "hello";
 176             s2 += '\0' + ",world";
 177         }
 178         static void MemTest()
 179         {
 180 
 181         }
 182         static void ReflectionTest()
 183         {//测试两种反射的效率问题
 184             //Type.GetType()只能在同一个程序集中使用,typeof则可以跨程序集(assembly)
 185             //通过下面的实测,发现typeof是比GetType快40多倍
 186             var timer = Stopwatch.StartNew();
 187             timer.Start();
 188 
 189             Type tx = Type.GetType("string");
 190             var tx1 = Type.GetType("float");
 191             timer.Stop();
 192 
 193             Console.WriteLine("T1= " + timer.Elapsed);//0.0000471
 194 
 195             timer.Restart();
 196 
 197             tx = typeof(string);
 198             tx1 = typeof(float);
 199 
 200             timer.Stop();
 201             Console.WriteLine("T2= " + timer.Elapsed);//0.0000011
 202         }
 203 
 204         static void TestDelegate()
 205         {
 206 
 207             //类C++11风格:指定初始化容量20,使用初始化列表给部分成员赋值
 208             var lst = new List<float>(20) { 1, 3, 4, 20, -2, 9, 0 };
 209             for (var i = 0; i < lst.Count; ++i)
 210             {
 211                 //使用下标进行随机访问,说明list不是一个真正的链表,而是类似STL的Vector
 212                 Console.WriteLine(lst[i]);
 213             }
 214 
 215             //public void Sort (Comparison comparison)      
 216             //public delegate int Comparison(T x, T y);
 217 
 218 
 219             //这是对调用List.Sort进行排序的写法,其中sort的定义及Comparison委托的定义如上
 220             lst.Sort(new Comparison<float>(delegate (float m1, float m2) //委托
 221             {
 222                 return 1;
 223             }));
 224             lst.Sort(delegate (float m1, float m2) //委托
 225             {
 226                 return 1;
 227             });
 228             lst.Sort((float m1, float m2) =>//Linq表达式
 229             {
 230                 return 1;
 231             });
 232             lst.Sort((m1, m2) => //Linq表达式
 233             {
 234                 return 1;
 235             });
 236 
 237         }
 238 
 239         static string TestRetStr()
 240         {//测试返回字符串是否会复制
 241             return "helloworld";
 242         }
 243 
 244         static void TestStrRet()
 245         {//h1 = h2 = h3说明它们返回的是同一个字符串的引用
 246             var s1 = TestRetStr();
 247             var s2 = TestRetStr();
 248             var s3 = TestRetStr();
 249             var h1 = s1.GetHashCode();
 250             var h2 = s1.GetHashCode();
 251             var h3 = s1.GetHashCode();
 252         }
 253         static void TestVirtualFuncCall()
 254         {
 255             var otx = new CTestChildX();
 256 
 257             otx.Update();//输出结果:child,如果注释1处函数不加override,输出结果为:base
 258             var oty = new CTestY();
 259             oty.Update();
 260             oty.OnUpdate();
 261 
 262         }
 263         static void TestStrModify()
 264         {
 265             var s1 = "hello";
 266             var s2 = s1;
 267             s1 += "world";
 268             Console.WriteLine(s2);
 269 
 270             var uns1 = s2.GetHashCode();
 271             Console.WriteLine(uns1);
 272         }
 273 
 274         static void Tests1()
 275         {
 276             var s1 = "hello";
 277             var uns1 = s1.GetHashCode();
 278             Console.WriteLine(uns1);
 279 
 280         }
 281 
 282         #endregion
 283 
 284         #region 2018.3.30
 285         #region ref out and template
 286         class myTemp//类入口
 287         {
 288             public T1 Add(T1 a, T1 b)
 289             {//模板类型不能直接相加,必须先转为动态类型,避开编译检查,运行时动态决定类型
 290                 dynamic da = a;
 291                 dynamic db = b;
 292                 return da + db;
 293             }
 294 
 295             public void tint()//注意C++不能这么写,所有模板参数必须由类入口传入
 296             {
 297                 Type t = typeof(T3);
 298                 WriteLine(t);
 299             }
 300         }
 301 
 302         delegate void refOutFunc(ref double t1, out double t2);
 303         delegate T TemplateDelegate(T a, U b);
 304         static void TestRefAndOut()
 305         {
 306             //ref, out 本质上都是引用
 307             //fef就为了传给函数使用,必须先初始化,但也可以传出数据,out是为了从函数中传出数据使用,不用初始化
 308             refOutFunc rof = delegate (ref double ax, out double bx) {
 309                 ax = 1; bx = 2;//ref out两种类型的变量都被更改了
 310             };
 311 
 312             double x1 = 0, x2;
 313             rof(ref x1, out x2);
 314         }
 315         static void TestTemplate()
 316         {
 317             var otp = new myTemp<int, int>();
 318             otp.tint<object>();
 319         }
 320         static T TempFunc(T a, U b)
 321         {
 322             return a;
 323         }
 324         static void TestBufAligin()
 325         {//自定义字节BUF的对齐测试
 326             int x = 9;
 327             int y = (x + 7) & ~7;
 328             WriteLine(y);
 329         }
 330         #endregion
 331 
 332         #endregion
 333 
 334         #region 2018.4.9
 335 
 336         //BUG??????
 337         //使用StopWatch测试运行时间
 338         //两段测试A和B
 339         //测试结果受测试顺序影响,后测要比先测耗时长了许多
 340 
 341         static void TestKeyIntStr()
 342         {//
 343             var idict = new Dictionary<int, string>();
 344             var sdict = new Dictionary<string, string>();
 345 
 346             for (int i = 0; i < 1000000; i++)
 347             {
 348                 var key = i * 2 + 1;
 349                 var v = i * i + "";
 350                 idict.Add(key, v);
 351                 sdict.Add(key + "", v);
 352             }
 353 
 354             //测试 A
 355             var t1 = 100000 * Test1(idict);
 356 
 357             //测试 B
 358             var t2 = 100000 * Test2(sdict);
 359 
 360             Console.WriteLine("t1: {0},t2: {1}", t1, t2);
 361             //Console.WriteLine("dt1: {0},dt2: {1}", dt1, dt2);
 362         }
 363         static float Test1(Dictionary<int, string> dict)
 364         {
 365             var timer = new Stopwatch();
 366             timer.Start();
 367             var it = dict[2001];
 368             var t1 = timer.ElapsedTicks;
 369             timer.Stop();
 370             return (float)((float)t1 / Stopwatch.Frequency);
 371         }
 372 
 373         static double Test2(Dictionary<string, string> dict)
 374         {
 375             var timer = new Stopwatch();
 376             timer.Start();
 377             var it = dict["2001"];
 378             var t1 = timer.ElapsedTicks;
 379             timer.Stop();
 380             return (float)((float)t1 / Stopwatch.Frequency);
 381         }
 382         #endregion
 383 
 384         #region 2018.7.7
 385         #region 数组的数组,二维数组
 386         static int[] returnArray()
 387         {
 388             //数组是引用类型,分配在堆上
 389             int[] arr = { 1, 2, 3, 4 }; //虽然这样写,其实等价于int[] arr = new int[]{1,2,3,4};
 390             return arr; //返回一个数组对象
 391         }
 392         static void TestArray() {
 393 
 394             //1,一维数组
 395             char[] arr = new char[2] { 'a', 'b' }; //必须全部初始化,或不初始化
 396             int[] iarr = new int[2] { 0, 1 };
 397             char[] sarr = new char[3];
 398 
 399             //2,数组的数组,锯齿数组
 400             char[][] d2arr = new char[2][];
 401             d2arr[0] = new char[30];
 402             d2arr[1] = new char[2] { 'a', 'b' };
 403             d2arr[0][1] = 'x';
 404 
 405             //3,二维数组,矩阵
 406             int[,] i2arr = new int[2, 3];
 407             for (var i = 0; i < 2; ++i)
 408             {
 409                 for (var j = 0; j < 3; ++j)
 410                 {
 411                     i2arr[i, j] = i * 3 + j;
 412                 }
 413             }
 414         }
 415         #endregion
 416         #region 字段初始化无法使用非静态(字段、方法、属性)
 417         delegate int mydelegate(int x);
 418         //-------------------------------------------------------------------------
 419         //字段初始化无法使用非静态(字段、方法、属性)
 420         //-------------------------------------------------------------------------
 421         float fxs;
 422         static float sfxs;
 423         //float fxs2 = fxs; //error
 424         float fxs3 = sfxs; //right,可用静态字段初始化
 425         float fxs4 = TestStaticInit(); //right,调用静态函数初始化
 426         static int TestStaticInit() { return 10; }
 427         mydelegate _mydel = (x) =>//LINQ为什么可以?,从下面可知,LINQ语句只相当于一堆初始化语句的集合
 428         {
 429             //int fx = fxs; //error
 430             return 20;
 431         };
 432 
 433         #endregion
 434         #region 默认访问修饰符
 435         //1,名字空间中,最外层类及接口的默认修饰符为internal,也就是本程序集可访问
 436         //2,类中,变量,成员,类中类的默认修饰符为private
 437         //3,结构中,同类
 438         //4,接口中,所有方法和属性都为public,接口中只能有方法,不能有变量
 439         interface IMyinterface
 440         {//接口中可以有方法,抽象属性,不可以有变量
 441             int Id { get; } //抽象属性,公有
 442             void Fly();  //方法,公有
 443         }
 444         #endregion
 445         #region 类模板继承
 446         class CTClass //多个where的写法
 447             where t1 : struct //必须是值类型
 448             where t2 : class //必须是引用类型
 449             where t3 : new() //必须有无参构造函数
 450         {
 451             float fx, fy;
 452             public static t1 Add(t1 a, t1 b)
 453             {
 454                 return (dynamic)a + (dynamic)b;
 455             }
 456         }
 457 
 458         //模板继承的几种方式
 459         //1,全特化
 460         class CDTClass : CTClass<int, CCmpBase, CCmpBase> { }
 461 
 462         //2,原样继承,注意基类的所有约束都要重写一遍
 463         class CDTX : CTClass
 464             where t1 : struct //必须是值类型
 465             where t2 : class //必须是引用类型
 466             where t3 : new() //必须有无参构造函数
 467         { }
 468         //3,偏特化,介于二者之间的形态
 469         #endregion
 470         #region 运算符重载
 471         class CCmpBase
 472         {//带有默认构造函数
 473             float _x;
 474         }
 475         class CComplex : CCmpBase
 476         {
 477             float real, image;
 478             public CComplex(float real, float image = 0)
 479             {
 480                 this.real = real;
 481                 this.image = image;
 482             }
 483 
 484             //一,类型转换 :数值转对象
 485             //CComplex cp = 2.1f 或 CComplex cp; cp = 2.1f;
 486             //C#从不调用类型转换构造函数进行类型转换
 487             public static implicit operator CComplex(float real)
 488             {
 489                 return new CComplex(real);
 490             }
 491 
 492             //二,类型转换:对象转bool
 493             public static explicit operator bool(CComplex cp)
 494             {
 495                 return cp.real != 0 && cp.image != 0;
 496             }
 497 
 498             //三,类型转换:对象转数值
 499             public static implicit operator float(CComplex cp)
 500             {
 501                 return cp.real;
 502             }
 503 
 504             //四,算术运算符重载 : +,-,*,/,%等
 505             //c#的运算符重载全部为静态函数,因此没有隐含参数
 506             //而C++运算符重载时可以重载为友元,绝大多数重载为类的成员函数,因此基本都有一个隐含参数(对象本身)
 507             public static CComplex operator +(CComplex a, CComplex b)
 508             {
 509                 return new CComplex(a.real + b.real, a.image + b.image);
 510             }
 511             public static CComplex operator ++(CComplex cp)
 512             {
 513                 cp.real++;
 514                 cp.image++;
 515                 return cp;
 516             }
 517 
 518             //五,不支持的运算符重载
 519             //1,不允许重载=运算符, C++可以,都不允许重载+=之类的
 520             //2,不允许重载括号()运算符
 521             //3,不允许重载[]运算符,因为它是索引器
 522             //public static implicit operator () (CComplex cp)
 523             //{
 524             //    return a;
 525             //}
 526 
 527             void TestPrivate()
 528             {
 529                 var cp = new CComplex(1, 3);
 530                 cp.real = 20;
 531                 cp.image = 30.0f;
 532             }
 533             public void PrintInfo()
 534             {
 535                 WriteLine("real:{0},image:{1}", real, image);
 536             }
 537         }
 538         static void TestOperatorOverload()
 539         {
 540             CComplex cp = new CComplex(1, 1);
 541 
 542             //1,同时支持前后向++,【不同于C++】
 543             cp++;
 544             ++cp;
 545 
 546             //2,但不允许连++, 【不同于C++】
 547             //cp++++或 ++++cp
 548 
 549             cp.PrintInfo();
 550 
 551             //3,支持连续+,【同于C++】
 552             CComplex cp1 = new CComplex(1, 1);
 553             var cpadd = cp + cp1 + cp1 + cp1;
 554             cpadd.PrintInfo();
 555             //类型转换运算符
 556             cp = 2.1f;
 557 
 558             //类型转换运算符
 559             //C++中是调用类型转换构造函数,而不是运算符重载
 560             CComplex cp2 = 1.0f;
 561 
 562         }
 563         #endregion
 564         #endregion
 565 
 566         #region 2018.7.11
 567         #region 两数相加函数模板实现
 568         static T MaxNum(T a, T b)
 569         {
 570             return ((dynamic)a > (dynamic)b) ? a : b;
 571         }
 572         #endregion
 573         #region thread lock
 574         //thread test
 575         class Account
 576         {
 577             private object thisLock = new object();
 578             int balance;
 579             Random r = new Random();
 580 
 581             public Account(int initial)
 582             {
 583                 balance = initial;
 584             }
 585 
 586             int Withdraw(int amount)
 587             {
 588                 if (balance < 0)
 589                 {
 590                     throw new Exception("Negative Balance");
 591                 }
 592 
 593                 lock (thisLock)
 594                 {
 595                     if (balance > amount)
 596                     {
 597                         WriteLine("before-withdraw: " + balance);
 598                         WriteLine("amount to withdraw: " + amount);
 599                         balance -= amount;
 600                         WriteLine("after withdraw: " + balance);
 601                         return amount;
 602                     }
 603                     else
 604                         return 0; //transaction rejected
 605                 }
 606             }
 607 
 608             public void DoTransactions()
 609             {
 610                 for (int i = 0; i < 100; ++i)
 611                 {
 612                     Withdraw(r.Next(1, 100));
 613                 }
 614             }
 615 
 616         }
 617 
 618         static void TestObjectLock()
 619         {
 620             Account acc = new Account(1000);
 621             Thread[] threads = new Thread[10];
 622             for (int i = 0; i < 10; ++i)
 623             {
 624                 threads[i] = new Thread(acc.DoTransactions);
 625             }
 626             for (int i = 0; i < 10; ++i)
 627             {
 628                 threads[i].Start();
 629                 //threads[i].Join();
 630             }
 631 
 632 
 633         }
 634         #endregion
 635         #region derive protected
 636         class A
 637         {
 638             float fxPrivate;
 639             protected int nProtected;
 640             protected A(int x) { }
 641         }
 642 
 643         class B : A     //c++的公有继承
 644         {
 645             B(String name, int x) : base(x) { }
 646 
 647             protected int nProtected;
 648             void TestDerive()
 649             {//这里的规则与C++完全一样:
 650                 //1,子类不能访问基类的私有成员,可以访问基类的保护和公有成员
 651                 //2,保护成员可以在本类中访问(不一定是本对象中)
 652                 nProtected = 20;
 653                 base.nProtected = 10;
 654                 var ob = new B("b", 1);
 655                 ob.nProtected = 30; //类中访问类的保护成员,但不是本对象的成员
 656 
 657             }
 658         }
 659         #endregion
 660         #endregion
 661 
 662         #region 2018.7.12
 663         #region 常量和静态变量静态类readonly
 664         //----------------------------------------------------------------------
 665         //常量和静态变量,静态类
 666         //----------------------------------------------------------------------
 667         //类的静态变量和常量,都属于类而不属于对象,不能用对象来调用,只能用类名调用
 668         //这不同于C++,是更合理的设计
 669         //常量的值在类定义时就确定了,不因对象而不同,因此存放在类中更合理
 670         class CNormclass
 671         {
 672             class CInclass
 673             {
 674                 public float fx = 20;
 675             }
 676             public int _id;
 677             public const string cname = "CNormalclass";
 678 
 679             //1,常量仅能修饰 :数字,bool,字符串,null引用
 680             //不能像C++那样定义一个常量对象,这真是太悲哀了,因为很多时候这可以加速数据传递,增加安全性
 681             //由于这个原因,C#的List.ToArray每次都只能返回一个内部数组的拷贝,因此使用list存储数量较大较复杂的数据时
 682             //不要轻易使用ToArray,直接用List就行了,它也支持下标索引方式取数组元素
 683             const CInclass lst = null;
 684 
 685             //2,readonly也不能实现常量对象的效果
 686             //readonly仅表示变量本身不能被赋值,但不阻止通过对象变量更改对象内的字段
 687             //onc.readonlyobj.fx = 20
 688             public float fx = 20;
 689 
 690             private readonly CInclass readonlyobj = new CInclass();
 691   
 692             public static void Test()
 693             {
 694                 //1,不能调用非静态字段或方法
 695                 //this._id = 20; //error,没有this指针
 696 
 697                 //2,可以调用常量字段
 698                 var lname = cname;
 699 
 700                 var onc = new CNormclass();
 701 
 702                 //私有变量在类的静态方法也可以访问
 703                 //2,虽然不能更改readonlyobj本身的值,却可以更改其内部成员的值,这就是readonly的作用
 704                 onc.readonlyobj.fx = 20; 
 705             }
 706         }
 707         static class C712//类中类,默认为私有
 708         {//静态类不能实例化,且只能声明:常量,静态常量,静态属性,静态方法
 709             public const int constX = 20; //1,常量
 710             public static int staticX = 0; //2,静态常量
 711             public static int ix { set; get; } //3,静态属性
 712 
 713             //一,【静态类中不能定义实例化字段】
 714             //public int _id; 
 715 
 716             //二,【静态类中不能定义实例化字段】
 717             //void Ctest(){ //【error: 静态类中不能定义实例化方法】
 718             //    this._id = 20;
 719             //}
 720 
 721             static void Test()//4,静态方法
 722             {
 723                 //三,【静态方法中不能调用非静态变量或方法,因为没有this指针】
 724                 //_id = 20;  //error 
 725 
 726                 //四,【可以调用常量字段,这与C++不同】
 727                 var c = constX;
 728             }
 729 
 730         }
 731         public const int ixd = 20;
 732         public static float fx = 20;
 733         public void Testff()
 734         {
 735             fx = 30; //等价于Program.fx = 30,而不是 this.fx = 30;
 736             Program.fx = 30;
 737             var tx = C712.constX;
 738             C712.staticX = 30;
 739             var ix = Program.ixd;
 740 
 741             //var oc7 = new C712(); //error 静态类不能创建实例
 742         }
 743         #endregion
 744         #region 事件和委托
 745         //--------------------------------------------------------------
 746         //event -test
 747         //--------------------------------------------------------------
 748         //使用event的好处,与delegate的区别:
 749         //event 本质上是一个委托,是做了一些安全措施的委托
 750         //1,event 定义的委托只允许 +=操作,不允许=赋值,这样防止事件被误清空,delegate则没有这些限制
 751         //2,event 定义的委托只能在本类中调用,可以防止外部触发,delegate没有这些限制
 752         //3,不使用事件,delegate方式完全可以实现类似限制,通过私有变量和公有函数结合方式
 753         class EventTest
 754         {
 755             public delegate void Delx(string s = "");
 756             Delx _delegate; // 私有委托,防止外部调用
 757             public event Delx _event; //公有事件,给外部通过+=注册使用,但_event()函数只能在本类调用,不能在类外调用
 758 
 759             //-------------------------------------------------------------
 760             //1 ,委托方式
 761             //-------------------------------------------------------------
 762             //(1)外部调用eventTest.AddListener(func)方式注册事件
 763             public void AddListener(Delx callback)
 764             {
 765                 _delegate += callback;
 766             }
 767             //(2)本类对象调用此函数触发事件
 768             void DelegateBrocast()
 769             {
 770                 _delegate("delegate"); //回调,触发事件
 771             }
 772 
 773             //-------------------------------------------------------------
 774             //2,事件方式
 775             //-------------------------------------------------------------
 776             //(1)外部使用 _event += 方式注册回调函数
 777             //(2)本类对象调用此函数触发事件
 778             void EventBrocast()
 779             {
 780                 _event("event");//回调,触发事件
 781             }
 782         }
 783         class Listener
 784         {
 785             public void OnEvent(string s)
 786             {
 787                 WriteLine("on-event---------------" + s);
 788             }
 789         }
 790         static void TestEventAndDelegate()
 791         {
 792             Listener l1 = new Listener();
 793             EventTest test = new EventTest();
 794 
 795             //1,事件方式
 796             test._event += l1.OnEvent; //注册事件
 797             //test._event = l1.OnEvent; //编译错误,事件只能使用+=,防止事件被清空
 798             //test._event("event"); //编译错误,事件不能在类外调用,事件只能由其所在类调用
 799 
 800             //2,委托方式
 801             test.AddListener(l1.OnEvent); //注册委托,通过函数对委托进行注册,因委托是私有的,可防止直接操作 test._delegate()
 802         }
 803 
 804         #endregion
 805         #region 文件和目录
 806         static void FileAndDirectory()
 807         {
 808             //-------------------------------------------------------------------------
 809             //文件对象的相关操作
 810             //-------------------------------------------------------------------------
 811             //方式一,使用工具类:File类,不需生成对象
 812             var file = File.Open("f:/test.txt", FileMode.Create, FileAccess.ReadWrite);
 813             //方式二,通过FileStream的对象
 814             var filestream = new FileStream("f:/test._txt", FileMode.Create, FileAccess.ReadWrite);
 815 
 816             //-------------------------------------------------------------------------
 817             //目录文件相关操作
 818             //-------------------------------------------------------------------------
 819             //方式一,实例化DirectoryInfo类
 820             var dir = new DirectoryInfo("f:/tolua");
 821             //(1)获取目录
 822             foreach (var d in dir.GetDirectories("*.*", SearchOption.AllDirectories))
 823             {
 824                 WriteLine(d.FullName);
 825             }
 826             //(2)获取文件
 827             foreach (var fileinfo in dir.GetFiles("*.*", SearchOption.AllDirectories))
 828             {
 829                 WriteLine(fileinfo.FullName);
 830             }
 831 
 832             //方式二,使用工具类: Directory类,不需生成对象
 833             //(1)获取目录
 834             var dirs = Directory.GetDirectories("f:/tolua", "*.*", SearchOption.AllDirectories);
 835             //(2)获取文件
 836             dirs = Directory.GetFiles("f:/tolua", "*.*", SearchOption.AllDirectories);
 837 
 838             for (int i = 0; i < dirs.Length; ++i)
 839             {//打印输出
 840                 WriteLine(dirs[i]);
 841             }
 842 
 843         }
 844         #endregion
 845         #endregion
 846 
 847         #region 2018.7.17
 848         #region 计算机中浮点数的存储
 849         static void TestFloat()
 850         {
 851             using (var ms = new MemoryStream())
 852             {
 853 
 854                 using (var br = new BinaryWriter(ms))
 855                 {
 856                     br.Write(125.5f);
 857                     var bytes = ms.GetBuffer();
 858                 }
 859             }
 860             unsafe
 861             {
 862                 float fx = 125.5f;
 863                 int* pfx = (int*)(&fx);
 864             }
 865 
 866         }
 867 
 868         #endregion
 869         #region 位移运算
 870         static void TestBitShift()
 871         {   //----------------------------------------------------------------------------
 872             //十进制数转二进制:
 873             //1,原理:将数X右移1位,最低位被移出,再左移,得到了数X0,则x-x0即为最低位的值
 874             //2,手工算法:根据1的原理,不断的对一个数整除2得余数,了终得到余数序列即是二进制的反向序列
 875             //3,左移等价于乘2,右移等价于除2,原理是乘法的竖式算法,
 876             //  101
 877             //x 010
 878             //-------           竖式算法适用于任何进制的加减法和乘法运算
 879             //  000
 880             //+101
 881             //-------
 882             // 1010
 883             //----------------------------------------------------------------------------
 884 
 885             int x = 7;
 886             List bits = new List(4);
 887             while (x != 0)
 888             {
 889                 var left = x - ((x >> 1) << 1);//<=> x - x/2*2
 890                 bits.Add((byte)left);
 891                 x = x >> 1;
 892             }
 893         }
 894         #endregion
 895         #region IEnumerableAndLinQ
 896         class Product
 897         {
 898             public int cateId;
 899             public string name;
 900         }
 901         class Category
 902         {
 903             public int id;
 904             public string name;
 905         }
 906         public static void TestIEnumerableAndLinq()
 907         {
 908             Category[] cates = new Category[]
 909             {
 910                 new Category{id = 1, name = "水果"},
 911                 new Category{id = 2, name = "饮料"},
 912                 new Category{id = 3, name = "糕点"},
 913             };
 914 
 915             Product[] products = new Product[]
 916             {
 917                 new Product{cateId=1, name = "apple"},
 918                 new Product{cateId=1, name = "banana"},
 919                 new Product{cateId=1, name = "pear/梨"},
 920                 new Product{cateId=1, name = "grape/葡萄"},
 921                 new Product{cateId=1, name = "pineapple/菠萝"},
 922                 new Product{cateId=1, name = "watermelon/西瓜"},
 923                 new Product{cateId=1, name = "lemon/柠檬"},
 924                 new Product{cateId=1, name = "mango/芒果"},
 925                 new Product{cateId=1, name = "strawberry/草莓"},
 926                 new Product{cateId=2, name = "bear/啤酒"},
 927                 new Product{cateId=2, name = "wine"},
 928                 new Product{cateId=3, name = "cake"},
 929                 new Product{cateId=3, name = "basicuit/饼干"},
 930 
 931             };
 932             var rets = cates.Where((x) => { return x.id > 1 && x.id < 5; });
 933             var iter = rets.GetEnumerator();
 934 
 935             while (iter.MoveNext())
 936             {
 937                 //WriteLine(iter.Current);
 938             }
 939 
 940             var set = from c in cates
 941 
 942                           //这里只能写一个条件,就是equals,用来关联两个表
 943                           //并且 c相关的条件只能写在equals左边,p相关条件只能写equals右边
 944                       join p in products on c.id equals p.cateId
 945 
 946                       //这里存放的是 products中的元素合集,而不是cates中的元素合集
 947                       //如果 from p in products join c in cates on c.id equals p.id into xgroups
 948                       //则xgroups中放的是cates中的元素集合
 949 
 950                       //这里是说将products中cateId等于c.id的所有元素放入一个组xgroups中
 951                       into xgroups
 952                       orderby c.id descending //对set中的结果进行降序排列
 953 
 954                       //where m > 4 && m < 10 //这里就可以写多个条件了
 955 
 956                       //from in 相当于外层循环,join in 相当于内层循环
 957                       //select在双层循环体中,每执行一次循环,【如果符合条件】,则执行一次结果选择
 958                       //双层循环完成后,最终将很多条选择提交给set
 959                       //【注意,如果不符合条件 select不会执行】
 960                       select new { cate = c.name, grp = xgroups }; //可以生成一个新的对象
 961 
 962             foreach (var p in set)
 963             {
 964                 WriteLine("分组:" + p.cate);
 965                 foreach (var g in p.grp)
 966                 {
 967                     WriteLine(g.cateId + "," + g.name);
 968                 }
 969             }
 970         }
 971 
 972         #endregion
 973         #region 类和继承
 974         class CTestX
 975         {
 976             public virtual void OnUpdate()
 977             {
 978                 Console.WriteLine("base-on-update");
 979             }
 980             public virtual void OnUpdate2()
 981             {
 982                 Console.WriteLine("base-on-update2");
 983             }
 984             public void Update()
 985             {
 986                 this.OnUpdate(); //注释1,如果子类有overide则调用子类的,否则调用自己的
 987             }
 988 
 989             public CTestX()
 990             {
 991 
 992             }
 993             protected CTestX(float fx)
 994             {
 995                 WriteLine("CTestX");
 996             }
 997 
 998             ~CTestX()
 999             {
1000                 WriteLine("~Ctestx");
1001             }
1002             public float fx;
1003             string name;
1004         }
1005 
1006         //子类不能访问基类任何私有的东西,包括方法,字段,属性,但它们都被继承了,属于子类,从实例内存可证
1007         //方法包括构造函数,即当基类是私有构造函数时,子类无法在初始化列表中调用base()来初始化
1008         class CTestChildX : CTestX
1009         {
1010             CTestX otestx;
1011 
1012             public CTestChildX() : base(1)//当基类为私有构造时,这里base无法调用
1013             {//当基类没有无参构造函数时,必须在初始化列表中初始化所有成员对象,如otestx
1014                 WriteLine("CTestChildX");
1015             }
1016 
1017             //注意overide与virtual的区别:
1018             //1,overide : 表明【函数是对基类的重写】 且 【本身是虚函数可被子类重写】
1019             //【函数会与基类、子类发生虚函数机制】
1020             //2,virtual : 仅表明函数是个虚函数,不会与基类发生虚函数机制
1021             //如果子类overide了该函数,则会与子类发生虚函数机制
1022             //3,多级继承中只要有一级没override,虚函数机制就会打断在此层级,见
1023 
1024             //override在编译层的机制是重写虚函数表中的函数地址
1025             //即将继承而来的虚函数表中的虚函数地址替换成本类的虚函数地址
1026             public static void TestDerive()
1027             {
1028                 //                 CTestX ox = new CTestChildX();
1029                 //                 ox.OnUpdate(); //base-on-update,无虚函数机制发生
1030                 //                 ox.OnUpdate2(); //child-on-update2,虚函数机制发生
1031                 //                 ox = new CTestY();
1032                 //                 ox.OnUpdate(); //base-on-update,无虚函数机制发生
1033                 CTestChildX ocx = new CTestZ();
1034                 ocx.OnUpdate(); //grand-child-on-update
1035             }
1036 
1037             public override void OnUpdate()
1038             {
1039                 Console.WriteLine("child-on-update");
1040             }
1041             public override void OnUpdate2()
1042             {
1043                 Console.WriteLine("child-on-update2");
1044             }
1045 
1046             ~CTestChildX() //不支持virtual
1047             {
1048                 WriteLine("~CTestChildX");
1049             }
1050         }
1051 
1052         class CTestY : CTestChildX
1053         {
1054             public override void OnUpdate()
1055             {
1056                 Console.WriteLine("grand-child-on-update");
1057 
1058             }
1059         }
1060         class CTestZ : CTestY
1061         {
1062             //因为这里的Update不是虚函数,因此
1063             public void OnUpdate()
1064             {
1065                 Console.WriteLine("grand-grand-child-on-update");
1066 
1067             }
1068         }
1069 
1070 
1071         struct CTX
1072         {
1073             void Test() {//不支持C++的const语法
1074             }
1075         }
1076 
1077         //1,不能继承结构,可以实现接口,
1078         //2,不能有虚函数
1079         struct CCTX //: CTX 
1080         {
1081             public void Test()
1082             {
1083 
1084             }
1085         }
1086 
1087         #endregion
1088         #region 字符串格式化
1089         static void TestStrFormat()
1090         {
1091             var str = Console.ReadLine();
1092             while (str != "exit")
1093             {
1094                 int ix;
1095                 Int32.TryParse(str, out ix); //ix = 120
1096                 var f1 = string.Format("{0 :d5}", ix); //"00120"
1097                 var f2 = string.Format("{0,-10:d5}", ix);//"00120     "
1098                 var f3 = string.Format("{0:x}", ix); //16进制输出到字符串
1099                 var f4 = string.Format("{0:0.000}", ix);//浮点数 120.000
1100                 Console.WriteLine("-----------begin-------------");
1101                 Console.WriteLine(f1);
1102                 Console.WriteLine(f2);
1103                 Console.WriteLine(f3);
1104                 Console.WriteLine(f4);
1105                 Console.WriteLine("------------end-------------");
1106 
1107                 str = Console.ReadLine();
1108             }
1109         }
1110         #endregion
1111         #endregion
1112 
1113         #region 2018.7.25
1114         #region 引用返回值(不是右值引用)
1115         static int[] _bookNum = new int[] { 1, 2, 3, 4, 5, 6 };
1116         static ref int GetBookNumber(int i)
1117         {
1118             int x = 10;
1119             return ref _bookNum[i];
1120         }
1121         static void TestRefReturn()
1122         {
1123             ref int rfn = ref GetBookNumber(1);
1124             rfn = 10101; //_bookNum[1]变成了 10101
1125             int vn = GetBookNumber(2);
1126             vn = 202; //_bookNum[2]未变,仍为3
1127 
1128             ref int x = ref vn;
1129         }
1130         #endregion
1131         #region 索引器
1132         class mylist
1133         {
1134             const int defaultCap = 4;
1135             T[] items;
1136             int count;
1137             int cap = defaultCap;
1138             public mylist(int cap = defaultCap)
1139             {
1140                 if (cap != defaultCap)
1141                     this.cap = cap;
1142                 items = new T[cap];
1143             }
1144             public T this[int idx] {
1145                 set {
1146                     items[idx] = value;
1147                 }
1148                 get {
1149                     return items[idx];
1150                 }
1151             }
1152 
1153         }
1154         enum Color
1155         {
1156             red,
1157             green,
1158             blue,
1159             yellow,
1160             cyan,
1161             purple,
1162             black,
1163             white,
1164         }
1165 
1166         static void TestIndexer(Color clr = Color.black)
1167         {
1168             mylist<string> lst = new mylist<string>();
1169             lst[1] = "hello";
1170         }
1171         #endregion
1172         #region 部分类
1173         //部分类的作用是可以把一个庞大的类拆分到多个文件,每个文件实现一部分
1174         //而不是实现像C++那样将声明与实现分开
1175         //若要实现声明(接口)与实现分开,应该使用抽象类或接口
1176         partial class CPartclass
1177         {
1178             public void ShowName() {
1179                 WriteLine("show name");
1180             }
1181         }
1182 
1183         partial class CPartclass
1184         {
1185             public void ShowAge(){
1186                 WriteLine("show age");
1187             }
1188         }
1189         static void TestPartclass()
1190         {
1191             CPartclass opc = new CPartclass();
1192             opc.ShowName();
1193             opc.ShowAge();
1194         }
1195         #endregion
1196         #region 动态分配对象数组C#与C++的区别
1197         struct xobject 
1198         {
1199             public float fx, fy, fz; //全是public的
1200         }
1201         static void TestDynamicAllocInCSharpCpp()
1202         {
1203             //1,对于引用类型数组,需要两步才能完成,因为数组中存放的是对象的引用
1204             //1.1 c#中
1205             xobject[] arr = new xobject[2];//这时候,只是分配了一个引用数组,arr[0],arr[1]均为null
1206             for (int i = 0; i < 2 ; i++)
1207             {
1208                 arr[i] = new xobject(); //为数组中每个引用申请对象
1209             }
1210 
1211             //1.2 c++中
1212             //xobject** pp = new xobject*[2];
1213             //pp[0] = new xobject();
1214             //pp[1] = new xobject();
1215 
1216             //2 对于值类型数组,则只需一步,因为数组中放的就是值,这在C#与CPP中都一样
1217             //2.1 C#中
1218             int[] iarr = new int[2];
1219             var a0 = iarr[0]; //0
1220             var a1 = iarr[1]; //0
1221 
1222             xobject[] varr = new xobject[3];
1223             varr[0].fx = 0.1f;
1224             varr[1].fy = 2.5f;
1225             varr[2].fz = 12;
1226 
1227             //2.2,在C++中
1228             //xobject* pobjs = new xobject[2]; //每个数组元素都是一个值类型对象
1229             //pobjs[0].fx = 20;
1230         }
1231         #endregion
1232         #region Object?语法
1233         static void TestobjAsk()
1234         {
1235             object obj = "hello";
1236             WriteLine(obj?.ToString());//如果obj不为null则调用tostring
1237         }
1238         #endregion
1239         #region C#默认字符编码及系统默认编码
1240         //默认编码为unicode,字符串本身的编码并不重要,字节读写时指定的编码才重要,如下面的BinaryWriter
1241         //Encoding.Default是当前系统的默认编码,并不是c#字符串的默认编码
1242         //Encoding.Default规则:汉字2字节,其它1字节
1243         static void TestDefaultStrEncoding()
1244         {
1245             string str = "hdd好";
1246             
1247             using (var ms = new MemoryStream())
1248             {
1249                 using (var br = new BinaryWriter(ms, Encoding.Default))
1250                 {
1251                     br.Write(str);
1252                     var len = ms.Length-1;
1253                     WriteLine(len);
1254 
1255                 }
1256             }
1257         }
1258         #endregion
1259         #region 属性attribute和反射
1260         class ReflectableClass
1261         {
1262             public float fx;
1263             public string str;
1264             //static const int x = 20; //这在C++中是可以的
1265             public void Printstr(string str, int idx)
1266             {
1267                 WriteLine(str + ":" + idx);
1268             }
1269         }
1270         static void TestReflect()
1271         {
1272             
1273             ReflectableClass ox = new ReflectableClass();
1274             Type t = typeof(ReflectableClass);//Type.GetType("ConsoleApplication1.Program.ReflectableClass");//ox.GetType();
1275             var tname = t.GetField("name");
1276             var tfx = t.GetField("fx");
1277             var func = t.GetMethod("Printstr", new Type[] {typeof(string),typeof(int) });
1278             func.Invoke(ox, new object[] { "helloworld", 1 });
1279 
1280             
1281             Type Ts = Type.GetType("System.String");
1282             var fs = Ts.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });
1283             var subs = fs.Invoke("hello world", new object[] { 1, 5 });
1284             WriteLine(subs);
1285         }
1286 
1287         static void TestAttribute()
1288         {
1289 
1290         }
1291 
1292         #endregion
1293         #endregion
1294         #region JSON
1295         void TestJson()
1296         {
1297 
1298         }
1299 
1300         #endregion
1301         #region CPP与CS间数据传递转换
1302 
1303         #endregion
1304         #region 线程
1305         #endregion
1306         #region 线程池
1307         #endregion
1308         #region 任务
1309         #endregion
1310         #region 程序集
1311         #endregion
1312         #region 多线程调试
1313         #endregion
1314 #region 扩展方法测试
1315         static void TestExtMethod()
1316         {
1317             ExtTargetCls oet = new ExtTargetCls();
1318             oet.methodExt(100);
1319             WriteLine(oet.sum);
1320         }
1321         #endregion
1322         class CMyList
1323         {
1324             //readonly仅表示变量本身不能被赋值,但不阻止通过对象变量更改对象内的字段
1325             //on._id = 100 //ok
1326             //on = new CNormclass() //error
1327 
1328             public readonly int[] rarr = { 1, 2, 3, 4 };
1329             public readonly int rix = 30; //可在初始化时赋值
1330             public readonly CNormclass on = new CNormclass();
1331             public CMyList()
1332             {
1333                 rix = 1; //可在构造函数中赋值
1334             }
1335             public int[] toArray()
1336             {
1337                 return rarr;
1338             }
1339 
1340             public void Clear()
1341             {
1342                 for(var i=0; i < rarr.Length; ++i)
1343                 {
1344                     rarr[i] = 0;
1345                 }
1346             }
1347             public static implicit operator CMyList(int ix)
1348             {
1349                 return new CMyList();
1350             }
1351 
1352         }
1353 
1354         // ctrl + w, t 可以察看所有待做任务
1355         static void Main(string[] args)
1356         {
1357             TestExtMethod();
1358             //TestReflect();
1359             //TestDefaultStrEncoding();
1360             //TestDynamicAllocInCSharpCpp();
1361             //TestPartclass();
1362             //TestRefReturn();
1363             //TestOperatorOverload();
1364             //    CTestChildX.TestDerive();
1365             //TestFloat();
1366 
1367             //var arr = returnArray();
1368  
1369         }
1370 
1371     }
1372     #region 扩展方法
1373     sealed class ExtTargetCls
1374     {
1375         public float sum = 10;
1376     }
1377     //扩展方法必须在顶级静态类中定义,不能是内部类
1378     //能不能通过扩展方法来修改类库以达到不法目的? 不能,因为扩展方法只能修改类的公有成员
1379     static class ExtentMethod
1380     {
1381         public static void methodExt(this ExtTargetCls target, float add)
1382         {
1383             target.sum += add;
1384         }
1385     }
1386     #endregion
1387 }

 

转载于:https://www.cnblogs.com/timeObjserver/p/9391470.html

你可能感兴趣的:(C# 全总结)