您当前的位置: 首页 >  c#

蔗理苦

暂无认证

  • 4浏览

    0关注

    88博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

2022-04-18 C# 第4篇——进阶

蔗理苦 发布时间:2022-04-18 15:37:02 ,浏览量:4

文章目录
        • 一、ArrayList
        • 二、Stack
        • 三、Queue
        • 四、Hashtable
        • 五、泛型
        • 六、泛型约束
        • 七、List
        • 八、Dictionary
        • 九、LinkedList
        • 十、泛型 Stack 和 Queue
        • 十一、委托
        • 十二、事件
        • 十三、匿名函数
        • 十四、Lambda表达式
        • 十五、闭包
        • 十六、List 排序
        • 十七、协变逆变
        • 十八、多线程
        • 十九、预处理器指令
        • 二十、反射
        • 二十一、特性
        • 二十二、迭代器
        • 二十三、特殊语法

一、ArrayList
// ArrayList的本质                                   
                                                            
// ArrayList是一个C#为我们封装好的类,                                   
// 它的本质是一个object类型的数组,                                       
// ArrayList类帮助我们实现了很多方法,                                    
// 比如数组的增删查改                                                 
                                                            
// 申明                                             
                                                            
// 需要引用命名空间 using System.Collections;                         
var array = new ArrayList();                                
                                                            
// 增删查改                                           
                                                            
// 增                                                   
                                                            
array.Add(1);                                               
array.Add("123");                                           
array.Add(true);                                            
array.Add(new object());                                    
array.Add(new Test());                                      
array.Add(1);                                               
array.Add(true);                                                
var array2 = new ArrayList();                               
array2.Add(123);                                            
// 范围增加(批量增加 把另一个list容器里面的内容加到后面)                            
array.AddRange(array2);                                       
array.Insert(1, "12345676");                                
Console.WriteLine(array[1]);                                                                                
                                                            
// 删                                                   
                                                            
// 移除指定元素 从头找 找到删                                            
array.Remove(1);                                            
// 移除指定位置的元素                                                 
array.RemoveAt(2);                                          
// 清空                                                        
// array.Clear();                                            
                                                            
// 查                                                   
                                                            
// 得到指定位置的元素                                                 
Console.WriteLine(array[0]);                                  
// 查看元素是否存在                                                  
if (array.Contains("1234")) Console.WriteLine("存在123");                                    
// 正向查找元素位置                                                  
// 找到的返回值 是位置 找不到 返回值 是-1                                    
var index = array.IndexOf(true);                            
Console.WriteLine(index);                                     
Console.WriteLine(array.IndexOf(false));                    
// 反向查找元素位置                                                  
// 返回时从头开始的索引数                                               
index = array.LastIndexOf(true);                            
Console.WriteLine(index);                                   
                                                            
// 改                                                   
                                                            
Console.WriteLine(array[0]);                                
array[0] = "999";                                           
Console.WriteLine(array[0]);                                
                                                            
// 遍历                                                  
                                                            
// 长度                                                        
Console.WriteLine(array.Count);                             
// 容量                                                        
// 避免产生过多的垃圾                                                 
Console.WriteLine(array.Capacity);                          
for (var i = 0; i  throw new NotImplementedException();                            
        set => throw new NotImplementedException();                            
    }                                                                          
}                                                                              
                                                                               
// 泛型方法                                                              
                                                                               
// 1.普通类中的泛型方法                                                                  
                                                                               
internal class Test2                                                           
{                                                                              
    public void TestFun(T value)                                            
    {                                                                          
        Console.WriteLine(value);                                              
    }                                                                          
                                                                               
    public void TestFun()                                                   
    {                                                                          
        // 用泛型类型 在里面做一些逻辑处理                                                     
        var t = default(T);                                                    
    }                                                                          
                                                                               
    public T TestFun(string v)                                              
    {                                                                          
        return default;                                                        
    }                                                                          
                                                                               
    public void TestFun(T t, K k, M m) { }                            
}                                                                              
                                                                               
// 2.泛型类中的泛型方法                                                                  
internal class Test2                                                        
{                                                                              
    public T value;                                                            
                                                                               
    public void TestFun(K k)                                                
    {                                                                          
        Console.WriteLine(k);                                                  
    }                                                                          
                                                                               
    // 这个不叫泛型方法 因为 T是泛型类申明的时候 就指定 在使用这个函数的时候                                    
    // 我们不能再去动态的变化了                                                             
    public void TestFun(T t) { }                                               
}                                                                              
                                                                               
// 泛型的作用                                                             
                                                                               
// 1.不同类型对象的相同逻辑处理就可以选择泛型                                                       
// 2.使用泛型可以一定程度避免装箱拆箱                                                           
// 举例:优化ArrayList                                                               
internal class ArrayList                                                    
{                                                                              
    private T[] array;                                                         
                                                                               
    public void Add(T value) { }                                               
                                                                               
    public void Remove(T value) { }                                            
}                                                                              
                                                                               
// 总结                                                                     
                                                                               
// 1.申明泛型时 它只是一个类型的占位符                                                          
// 2.泛型真正起作用的时候 是在使用它的时候                                                        
// 3.泛型占位字母可以有n个用逗号分开                                                           
// 4.泛型占位字母一般是大写字母                                                              
// 5.不确定泛型类型时 获取默认值 可以使用default(占位字符)                                           
// 6.看到包裹的字母 那肯定是泛型                                                                  
六、泛型约束

​ 让泛型的类型有一定的限制 ​ 关键字:where ​ 泛型约束一共有6种

  1. 值类型 where 泛型字母:struct
  2. 引用类型 where 泛型字母:class
  3. 存在无参公共构造函数 where 泛型字母:new()
  4. 某个类本身或者其派生类 where 泛型字母:类名
  5. 某个接口的派生类型 where 泛型字母:接口名
  6. 另一个泛型类型本身或者派生类型 where 泛型字母:另一个泛型字母
where 泛型字母:(约束的类型)
// 各泛型约束讲解                                                         
                                                                             
// 值类型约束                                                                
                                                                             
internal class Test1 where T : struct                                     
{                                                                            
    public T value;                                                          
                                                                             
    public void TestFun(K v) where K : struct { }                         
}                                                                            
                                                                             
// 引用类型约束                                                               
                                                                             
internal class Test2 where T : class                                      
{                                                                            
    public T value;                                                          
                                                                             
    public void TestFun(K k) where K : class { }                          
}                                                                            
                                                                             
// 公共无参构造约束                                                             
                                                                             
internal class Test3 where T : new()                                      
{                                                                            
    public T value;                                                          
                                                                             
    public void TestFun(K k) where K : new() { }                          
}                                                                            
                                                                             
internal class Test1 { }                                                     
                                                                             
internal class Test2                                                         
{                                                                            
    public Test2(int a) { }                                                  
}                                                                            
                                                                             
// 类约束                                                                  
                                                                             
internal class Test4 where T : Test1                                      
{                                                                            
    public T value;                                                          
                                                                             
    public void TestFun(K k) where K : Test1 { }                          
}                                                                            
                                                                             
internal class Test3 : Test1 { }                                             
                                                                             
// 接口约束                                                                 
                                                                             
internal interface IFly { }                                                  
                                                                             
internal interface IMove : IFly { }                                          
                                                                             
internal class Test4 : IFly { }                                              
                                                                             
internal class Test5 where T : IFly                                       
{                                                                            
    public T value;                                                          
                                                                             
    public void TestFun(K k) where K : IFly { }                           
}                                                                            
                                                                             
// 另一个泛型约束                                                              
                                                                             
internal class Test6 where T : U                                       
{                                                                            
    public T value;                                                          
                                                                             
    public void TestFun(K k) where K : V { }                           
}                                                                            
                                                                             
// 约束的组合使用                                                         
                                                                             
internal class Test7 where T : class, new() { }                           
                                                                             
// 多个泛型有约束                                                         
                                                                             
internal class Test8 where T : class, new() where K : struct { }                                                           
七、List
// List的本质                                              
                                                                  
// List是一个C#为我们封装好的类,                                              
// 它的本质是一个可变类型的泛型数组,                                               
// List类帮助我们实现了很多方法,                                               
// 比如泛型数组的增删查改                                                     
                                                                  
// 申明                                                   
                                                                  
// 需要引用命名空间                                                        
// using System.Collections.Generic                                
var list  = new List();                                      
var list2 = new List();                                   
var list3 = new List();                                     
                                                                  
// 增删查改                                                 
                                                                  
// 增                                                         
                                                                  
list.Add(1);                                                      
list.Add(2);                                                      
list.Add(3);                                                      
list.Add(4);                                                      
                                                                  
list2.Add("123");                                                 
                                                                  
var listStr = new List();                                 
listStr.Add("123");                                               
list2.AddRange(listStr);                                          
                                                                  
list.Insert(0, 999);                                              
Console.WriteLine(list[0]);                                       
                                                                  
// 删                                                         
                                                                  
// 1.移除指定元素                                                        
list.Remove(1);                                                   
// 2.移除指定位置的元素                                                     
list.RemoveAt(0);                                                 
// 3.清空                                                            
list.Clear();                                                     
                                                                  
list.Add(1);                                                      
list.Add(2);                                                      
list.Add(3);                                                      
list.Add(4);                                                      
list.Add(1);                                                      
                                                                  
// 查                                                         
                                                                  
// 1.得到指定位置的元素                                                     
Console.WriteLine(list[0]);                                       
// 2.查看元素是否存在                                                      
if (list.Contains(1)) Console.WriteLine("存在元素 1");                
// 3.正向查找元素位置                                                      
//  找到返回位置 找不到 返回-1                                                
var index = list.IndexOf(5);                                      
Console.WriteLine(index);                                         
// 4.反向查找元素位置                                                      
//  找到返回位置 找不到 返回-1                                                
index = list.LastIndexOf(2);                                      
Console.WriteLine(index);                                         
                                                                  
// 改                                                         
                                                                  
Console.WriteLine(list[0]);                                       
list[0] = 99;                                                     
Console.WriteLine(list[0]);                                       
                                                                  
// 遍历                                                   
                                                                  
// 长度                                                              
Console.WriteLine(list.Count);                                    
// 容量                                                              
// 避免产生垃圾                                                          
Console.WriteLine(list.Capacity);                                 
for (var i = 0; i                                                                         
// {                                                                                
//     //函数体                                                                        
// };                                                                               
                                                                                   
// 使用                                                                    
                                                                                   
// 1.无参无返回                                                                          
Action a = () => { Console.WriteLine("无参无返回值的lambad表达式"); };                       
a();                                                                               
                                                                                   
// 2.有参                                                                             
Action a2 = value => { Console.WriteLine("有参数Lambad表达式{0}", value); };        
a2(100);                                                                           
                                                                                   
// 3.甚至参数类型都可以省略 参数类型和委托或事件容器一致                                                     
Action a3 = value => { Console.WriteLine("省略参数类型的写法{0}", value); };           
a3(200);                                                                           
                                                                                   
// 4.有返回值                                                                           
Func a4 = value => {                                                  
    Console.WriteLine("有返回值有参数的那么大表达式{0}", value);                                 
    return 1;                                                                      
};                                                                                 
Console.WriteLine(a4("123123"));                                                   
                                                                                   
// 其它传参使用等和匿名函数一样                                                                   
// 缺点也是和匿名函数一样的                                                                   
十五、闭包
// 闭包                                                      
                                                                     
// 内层的函数可以引用包含在它外层的函数的变量                                              
// 即使外层函数的执行已经终止                                                      
// 注意:                                                                
// 该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值。                                    
                                                                     
internal class Test                                                  
{                                                                    
    public Test() {                                                  
        int value = 10;                                              
        // 这里就形成了闭包                                                   
        // 因为 当构造函数执行完毕时  其中申明的临时变量value的声明周期被改变了                     
        action = () => { Console.WriteLine(value); };                
                                                                     
        for (int i = 0; i  { Console.WriteLine(index); };           
        }                                                            
    }                                                                
                                                                     
    public event Action action;                                      
                                                                     
    public void DoSomthing() {                                       
        action();                                                    
    }  
}
十六、List 排序

​ 系统自带的变量 (int,float,double,…) 一般都可以直接 Sort ​ 自定义类 Sort 有两种方式

  1. 继承接口 IComparable
  2. 在 Sort 中传入委托函数
internal class Item : IComparable                                                        
{                                                                                              
    public int money;                                                                          
                                                                                               
    public Item(int money) {                                                                   
        this.money = money;                                                                    
    }                                                                                          
                                                                                               
    public int CompareTo(Item other) {                                                         
        // 返回值的含义                                                                               
        // 小于0:                                                                                 
        // 放在传入对象的前面                                                                            
        // 等于0:                                                                                 
        // 保持当前的位置不变                                                                            
        // 大于0:                                                                                 
        // 放在传入对象的后面                                                                            
                                                                                               
        // 可以简单理解 传入对象的位置 就是0                                                                   
        // 如果你的返回为负数 就放在它的左边 也就前面                                                               
        // 如果你返回正数 就放在它的右边 也就是后面                                                                
                                                                                               
        if (money > other.money)                                                               
            return -1;                                                                         
        return 1;                                                                              
    }                                                                                          
}                                                                                              
                                                                                               
internal class ShopItem                                                                        
{                                                                                              
    public int id;                                                                             
                                                                                               
    public ShopItem(int id) {                                                                  
        this.id = id;                                                                          
    }                                                                                          
}                                                                                              
                                                                                               
internal class Program                                                                         
{                                                                                              
    private static void Main(string[] args) {                                                  
        Console.WriteLine("List排序");                                                           
                                                                                               
        // List自带排序方法                                                                
                                                                                               
        List list = new List();                                                      
        list.Add(3);                                                                           
        list.Add(2);                                                                           
        list.Add(6);                                                                           
        list.Add(1);                                                                           
        list.Add(4);                                                                           
        list.Add(5);                                                                           
        for (int i = 0; i  b.id ? 1 : -1; });                            
                                                                                                
        for (int i = 0; i  b.id)                                                                       
            return -1;                                                                         
        return 1;                                                                              
    }                                                                                          
}                                                                                              
十七、协变逆变

​ 协变: ​ 和谐的变化,自然的变化 ​ 因为里氏替换原则,父类可以装子类,所以子类变父类

​ 比如 string 变成 object,感受是和谐的

​ 逆变: ​ 逆常规的变化,不正常的变化 ​ 因为里氏替换原则 父类可以装子类 但是子类不能装父类,所以父类变子类

​ 比如 object 变成 string,感受是不和谐的

​ 协变和逆变是用来修饰泛型的 ​ 协变:out ​ 逆变:in ​ 用于在泛型中修饰泛型字母的,只有泛型接口和泛型委托能使用

// 作用                                                                
                                                                               
// 1.返回值 和 参数                                                                   
// 用out修饰的泛型 只能作为返回值                                                            
internal delegate T TestOut();                                          
                                                                               
// 用in修饰的泛型 只能作为参数                                                              
internal delegate void TestIn(T t);                                      
                                                                               
// 2.结合里氏替换原则理解                                                                 
internal class Father { }                                                      
                                                                               
internal class Son : Father { }                                                                                                                      
                                                                               
internal class Program                                                         
{                                                                              
    private static void Main(string[] args) {                                  
        Console.WriteLine("协变逆变");                                             
                                                                               
        // 作用(结合里氏替换原则理解)                                            
                                                                               
        // 协变 父类总是能被子类替换                                                        
        // 看起来 就是 son ——> father                                               
        TestOut os = () => new Son();                                     
                                                                               
        TestOut of = os;                                               
        Father          f  = of(); // 实际上 返回的 是os里面装的函数 返回的是Son                 
                                                                               
        // 逆变 父类总是能被子类替换                                                        
        // 看起来像是 father——>son 明明是传父类 但是你传子类 不和谐的                                
        TestIn iF = value => { };                                      
                                                                               
        TestIn iS = iF;                                                   
                                                                               
        iS(new Son()); // 实际上 调用的是 iF                                              
    }                                                                          
}                                                                              

​ 协变 out ​ 逆变 in ​ 用来修饰泛型替代符,只能修饰接口和委托中的泛型

​ 作用两点:

  1. out 修饰的泛型类型只能作为返回值类型 ,in 修饰的泛型类型只能作为参数类型
  2. 遵循里氏替换原则,用 out 和 in 修饰的泛型委托,可以相互装载(有父子关系的泛型)

​ 协变:父类泛型委托装子类泛型委托

​ 逆变:子类泛型委托装父类泛型委托

十八、多线程
private static void NewThreadLogic() {                     
    // 新开线程 执行的代码逻辑 在该函数语句块中                                
    while (isRuning)                                       
        // Thread.Sleep(1000);                              
        // Console.WriteLine("新开线程代码逻辑");                   
    {                                                      
        lock (obj) {                                       
            Console.SetCursorPosition(10, 5);              
            Console.ForegroundColor = ConsoleColor.Yellow; 
            Console.Write("■");                            
        }                                                  
    }                                                      
}                                                          

// 线程类 Thread                                                                 
// 需要引用命名空间 using System.Threading;                                           
// 1.申明一个新的线程                                                                 
//   注意 线程执行的代码 需要封装到一个函数中                                                    
//   新线程 将要执行的代码逻辑 被封装到了一个函数语句块中                                              
Thread t = new Thread(NewThreadLogic);                                       
// 2.启动线程                                                                     
t.Start();                                                                   
                                                                             
// 3.设置为后台线程                                                                  
// 当前台线程都结束了的时候,整个程序也就结束了,即使还有后台线程正在运行                                        
// 后台线程不会防止应用程序的进程被终止掉                                                        
// 如果不设置为后台线程 可能导致进程无法正常关闭                                                    
t.IsBackground = true;                                                       
                                                                             
// 4.关闭释放一个线程                                                                 
// 如果开启的线程中不是死循环 是能够结束的逻辑 那么 不用刻意的去关闭它                                        
// 如果是死循环 想要中止这个线程 有两种方式                                                      
// 4.1-死循环中bool标识                                                             
// Console.ReadKey();                                                         
                                                                             
// isRuning = false;                                                          
                                                                             
// Console.ReadKey();                                                         
                                                                             
// 4.2-通过线程提供的方法(注意在.Net core版本中无法中止 会报错)                                     
// 中止线程                                                                       
// try                                                                        
// {                                                                          
//     t.Abort();                                                             
//     t = null;                                                              
// }                                                                          
// catch                                                                      
// {                                                                          
                                                                              
// }                                                                          
                                                                             
// 5.线程休眠                                                                     
// 让线程休眠多少毫秒  1s = 1000毫秒                                                     
// 在哪个线程里执行 就休眠哪个线程                                                           
// Thread.Sleep(1000);                                                        
                                                                             
// 线程之间共享数据                                                        
                                                                             
// 多个线程使用的内存是共享的,都属于该应用程序(进程)                                                 
// 所以要注意 当多线程 同时操作同一片内存区域时可能会出问题                                              
// 可以通过加锁的形式避免问题                                                              
                                                                             
// lock                                                                       
// 当我们在多个线程当中想要访问同样的东西 进行逻辑处理时                                                
// 为了避免不必要的逻辑顺序执行的差错                                                          
// lock(引用类型对象)                                                               
                                                                             
while (true) {                                                               
    lock (obj) {                                                             
        Console.SetCursorPosition(0, 0);                                     
        Console.ForegroundColor = ConsoleColor.Red;                          
        Console.Write("●");                                                  
    }                                                                        
}                                                                            
                                                                             
// 多线程对于我们的意义                                                      
                                                                             
//可以用多线程专门处理一些复杂耗时的逻辑                                                        
//比如 寻路、网络通信等等                                                               

​ 多线程是多个可以同时执行代码逻辑的“管道” ​ 可以通过代码开启多线程,用多线程处理一些复杂的可能影响主线程流畅度的逻辑 ​ 关键字 Thread

十九、预处理器指令
            // 1
            // #define
            // 定义一个符号,类似一个没有值的变量
            // #undef
            // 取消define定义的符号,让其失效
            // 两者都是写在脚本文件最前面
            // 一般配合 if指令使用 或配合特性

            // 2
            // #if
            // #elif
            // #else
            // #endif
            // 和if语句规则一样,一般配合#define定义的符号使用
            // 用于告诉编译器进行编译代码的流程控制

            // 如果发现有Unity4这个符号 那么其中包含的代码 就会被编译器翻译
            // 可以通过 逻辑或 和 逻辑与 进行多种符号的组合判断
#if Unity4
            Console.WriteLine("版本为Unity4");
#elif Unity2017 && IOS
            Console.WriteLine("版本为Unity2017");
            // #warning 这个版本 不合法
            // #error 这个版本不准执行
#else
            Console.WriteLine("其它版本");
#endif

            // 3
            // #warning
            // #error
            // 告诉编译器
            // 是报警告还是报错误
            // 一般还是配合if使用
二十、反射

(一)概念

  1. 程序集

    程序集是经由编译器编译得到的,供进一步编译执行的那个中间产物

    在 WINDOWS 系统中,它一般表现为后缀为.dll(库文件)或者是.exe(可执行文件)的格式

    程序集就是我们写的一个代码集合,我们现在写的所有代码

    最终都会被编译器翻译为一个程序集供别人使用 比如一个代码库文件(dll)或者一个可执行文件(exe)

  2. 元数据

    元数据就是用来描述数据的数据 这个概念不仅仅用于程序上,在别的领域也有元数据

    程序中的类,类中的函数、变量等等信息就是程序的元数据 有关程序以及类型的数据被称为元数据,它们保存在程序集中

  3. 反射

    程序正在运行时,可以查看其它程序集或者自身的元数据。 一个运行的程序查看本身或者其它程序的元数据的行为就叫做反射

    在程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息 类,函数,变量,对象等等,实例化它们,执行它们,操作它们

  4. 反射的作用

    因为反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性

    • 程序运行时得到所有元数据,包括元数据的特性
    • 程序运行时,实例化对象,操作对象
    • 程序运行时创建新对象,用这些对象执行任务

(二)Type

​ Type(类的信息类) ​ 它是反射功能的基础!它是访问元数据的主要方式。 ​ 使用 Type 的成员获取有关类型声明的信息 ​ 有关类型的成员(如构造函数、方法、字段、属性和类的事件)

internal class Test                             
{                                               
    private readonly int    i = 1;              
    public           int    j;                  
    public           string str = "123";        
                                                
    public Test() { }                           
                                                
    public Test(int i) {                        
        this.i = i;                             
    }                                           
                                                
    public Test(int i, string str) : this(i) {  
        this.str = str;                         
    }                                           
                                                
    public void Speak() {                       
        Console.WriteLine(i);                   
    }               
}
  1. 获取 Type
// 1.万物之父object中的 GetType()可以获取对象的Type     
int  a    = 42;                           
Type type = a.GetType();                  
Console.WriteLine(type);                  
// 2.通过typeof关键字 传入类名 也可以得到对象的Type         
Type type2 = typeof(int);                 
Console.WriteLine(type2);                 
// 3.通过类的名字 也可以获取类型                        
//   注意 类名必须包含命名空间 不然找不到                   
Type type3 = Type.GetType("System.Int32");
Console.WriteLine(type3);                 
  1. 得到类的程序集信息
// 可以通过Type可以得到类型所在程序集信息            
Console.WriteLine(type.Assembly);  
Console.WriteLine(type2.Assembly); 
Console.WriteLine(type3.Assembly); 
  1. 获取类中的所有公共成员
// 首先得到Type                                                         
Type t = typeof(Test);                                             
// 然后得到所有公共成员                                                       
// 需要引用命名空间 using System.Reflection;                                
MemberInfo[] infos = t.GetMembers();                               
for (int i = 0; i             
关注
打赏
1657823434
查看更多评论
0.1611s