C#【进阶】协变逆变 多线程 预处理指令

协变逆变 多线程 预处理指令

在这里插入图片描述

1、协变逆变

1、协变逆变概念

协变:
    和谐自然的变化
    里氏替换原则,父类泛型委托装子类泛型委托
    所以子类变父类,比如string变object感受是和谐自然的
    
逆变:
    子类泛型委托装父类泛型委托
	父类变子类,比如Object变string,感受是不和谐的
	
协变和逆变是用来修饰泛型的
    协变:out
    逆变:in
用于在泛型中修饰泛型字母的
只有泛型接口和泛型委托才能使用

2、作用

1、返回值和参数
    
    用out修饰的泛型类型,只能作为返回值类型
    delegate T TestOut<out T>();
	interface Test<out T>{ T TestFun();}

    用in修饰的泛型类型,只能作为参数类型
    delegate void TestIn<in T>(T t);

2、结合里氏替换原则理解
    用out和in修饰的泛型委托,可以相互装载(有继承关系的泛型)
//协变 父类总是能被子类替换
    TestOut<Son> os = () =>
    {
        return new Son();
    };
    //用out修饰,可自动判断返回值有无继承关系
    TestOut<Father> of = os;
    //看起来调用了父类,实际上代码通过协变,返回的是os里面的函数,返回的是Son
    Father f = of();

//逆变 父类总是能被子类替换
    TestIn<Father> iF = (value) =>{};
    TestIn<Son> iS = iF;
    iS(new Son());

    delegate T TestOut<out T>();
    delegate void TestIn<in T>(T t);

    class Father { }
    class Son : Father { }

2、多线程

1、进程

运行应用程序就是在操作系统上开启了一个进程
    编程可以理解为制作进程

2、线程概念

线程:
	代码依次执行的一条路径
    进程可以并发多个线程
    在线程里面编程

3、多线程概念

同时运行代码的多条线程

4、语法

线程类 Thread
    1、声明一个新的线程
    线程执行的代码,需要封装到一个函数中
	//声明线程   
    Thread t = new Thread(NewThreadLogic);
2、启动线程
    t.Start();
3、设置为后台线程
    //若不设置后台线程,可能导致进程无法正常关闭
    t.IsBackground = true;
    
    void NewThreadLogic()
    {
        Console.WriteLine("新开的代码逻辑");
    }
4、关闭释放一个线程
    1、加bool标识
    2、通过线程提供的方法(在.Net core版本无法中止)
    t.Abort();
	t = null;
5、线程休眠
    //单位毫秒 1s = 1000毫秒
    Thread.Sleep(1000);

5、线程之间共享数据

多个线程使用的内存是共享的,都属于该应用程序(进程)
当多线程同时操作同一片内存区域时可能会出问题
可以通过加锁的形式避免问题
    lock(obj){}

6、多线程的意义

可以用多线程专门处理一些复杂耗时的逻辑
比如:寻路、网络通信等
思考 多线程移动方块
//控制台有一个■,移动。用多线程来检测输入,控制转向
//移动的方向。位置、绘制、擦除、转向

Console.CursorVisible = false;
Icon i = new Icon(10, 5, E_MoveDir.Right);
i.Drow();

Thread t = new Thread(NewThreadLogic);
t.Start();

while (true)
{
    Thread.Sleep(300);
    i.Clear();
    i.Move();
    i.Drow();
}

void NewThreadLogic()
{
    while (true)
    {
        switch (Console.ReadKey(true).Key)
        {
            case ConsoleKey.W:
                i.ChangeDir(E_MoveDir.Up);
                break;
            case ConsoleKey.S:
                i.ChangeDir(E_MoveDir.Down);
                break;
            case ConsoleKey.A:
                i.ChangeDir(E_MoveDir.Left);
                break;
            case ConsoleKey.D:
                i.ChangeDir(E_MoveDir.Right);
                break;
        }
    }
}

enum E_MoveDir
{
    Up,
    Down,
    Left,
    Right,
}
class Icon
{
    //当前移动方向
    public E_MoveDir dir;
    public int x;
    public int y;

    public Icon(int x, int y,E_MoveDir dir)
    {
        this.x = x;
        this.y = y;
        this.dir = dir;
    }
    public void Move()
    {
        switch (dir)
        {
            case E_MoveDir.Up:
                y--;
                break;
            case E_MoveDir.Down:
                y++;
                break;
            case E_MoveDir.Left:
                x -= 2;
                break;
            case E_MoveDir.Right:
                x += 2;
                break;
            default:
                break;
        }
    }
    public void Drow()
    {
        Console.SetCursorPosition(x, y);
        Console.Write("■");
    }
    public void Clear()
    {
        Console.SetCursorPosition(x, y);
        Console.Write("  ");
    }
    public void ChangeDir(E_MoveDir dir)
    {
        this.dir = dir;
    }
}

3、预处理指令

1、编译器概念

编译器是一种翻译程序
它用于将源语言程序翻译为目标语言程序

源语言程序:
	某种程序设计语言写成,比如C#、c、c++、Java
目标语言程序:
	二进制数表示的伪机器代码写的程序

2、预处理器指令

预处理器指令:
	指导编译器,在实际编译开始之前对信息进行预处理
	预处理器指令都是以#开始

3、常见的预处理器指令

1
#define
	定义一个符号,类似一个没有值的变量
	一般配合if、特性使用
#undef

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

    #define Unity4
    #define Unity2017
    #define IOS

    //#undef Unity4
    #if Unity4
    Console.WriteLine("版本为Unity4");
    #elif Unity2017 && IOS
    Console.WriteLine("版本为Unity2017");
    #else
    Console.WriteLine("其他版本");
    #endif 
        
3
#warning
#error
总结
预处理指令
可以让代码还没有编译之前就可以进行一些预处理判断
在Unity中会用来进行一些平台或者版本的判断
决定不同的版本或者不同的平台使用不同的逻辑代码
思考 预处理器指令实现
//请使用预处理器指令实现
//写一个函数计算两个数
//当是Unity5版本时算加法
//当是Unity2017版本时算乘法
//当是Unity2020版本时算减法

//#define Unity5
#define Unity2017
#define Unity2020
Console.WriteLine(Calc(1,2));
int Calc(int a,int b)
{
#if Unity5
return a+b;
#elif Unity2017
return a*b;
#elif Unity2020
return a-b;
#else
    return 0;
#endif
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值