using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class TestUsing : IDisposable
{
    public void Dispose()
    {
        
    }
}

public class Person
{
    public string name;
    public bool sex;
    public string number;
    public string email;

    public void Deconstruct(out string n, out bool sex) => (n, sex) = (this.name, this.sex);

    public void Deconstruct(out string n, out bool sex, out string number) => (n, sex, number) = (this.name, this.sex, this.number);

    public void Deconstruct(out string n, out bool sex, out string number, out string email)
    {
        n = name;
        sex = this.sex;
        number = this.number;
        email = this.email;
    }
}

public class Lesson10 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 C#8对应Unity版本
        //Unity 2020.3 支持 C# 8 
        //但部分新特性在该版本Unity中不被支持
        //筛选了一些比较实用的特性给大家讲解
        #endregion

        #region 知识点二 C#8新特性功能和新语法有哪些
        //1.Using 声明
        //2.静态局部函数
        //3.Null 合并赋值
        //4.解构函数Deconstruct 

        //5.模式匹配增强
        #endregion

        #region 知识点三 静态局部函数
        //知识回顾:
        //在C#7新语法中我们学习了局部函数
        //局部函数知识点回顾
        //定义位置:在函数内部申明的一个新函数
        //注意:
        //局部函数只能在申明该函数的内部使用
        //局部函数可以使用所在函数中的变量
        //作用:业务逻辑的封装
        //建议:把局部函数写在要主要逻辑的后面,方便查看
        print(CalcInfo(10));

        //新知识点:
        //静态局部函数需要在局部函数前加入static关键字
        //该特性使得局部函数不能再使用封闭范围(上层方法)中的任何变量
        //说明 该局部函数只能用于处理不依赖外部参数的独立逻辑,或通过参数传入所有需要数据
        #endregion

        #region 知识点四 Using 声明
        //知识回顾:
        //在数据持久化或xml读写知识中
        //我们学习了using相关的知识
        //using(对象声明)
        //{
        //使用对象进行相关操作 对象将被释放掉
        //当对象类型实现了 IDisposable接口时 会自动调用该对象的 Dispose方法 释放资源
        //using一般用于 内存占用比较大 或者 文件读写时  进行使用 
        //}
        //示例回顾:
        using(StreamWriter strem = new StreamWriter("文件路径"))
        {
            //对该变量进行逻辑处理 该变量只在当前作用域使用
            strem.Write(true);
            strem.Write(1.2f);
            strem.Flush();
            strem.Close();
        }//当作用域结束时 会 自动调用 对象的 Dispose方法 释放对象

        //新知识点:
        //Using 声明是对using语句法的简写
        //当执行到作用域结束时 会 自动调用 对象的 Dispose方法 释放对象

        using StreamWriter s2 = new StreamWriter("文件路径");
        //对该对象进行逻辑处理
        s2.Write(5);
        s2.Flush();
        s2.Close();
        //当执行到上层作用域结束时就会释放该对象

        //注意:使用using语法时,对象的类型必须继承System.IDisposable接口
        //因为需要具备Dispose方法才能被调用,未继承该接口的对象会报错
        using TestUsing t = new TestUsing();
        #endregion

        #region 知识点五 Null 合并赋值
        //知识回顾:
        //在C#基础语法知识中我们学习了 ?? 空合并运算符
        //回顾空合并运算符知识点
        // 左值 ?? 右值
        // 当左值为null 时返回右值 否则返回左值
        // 只要是允许为null的类型都可以
        // 示例 
        string str = null;
        string str2 = str ?? "234";
        print(str2);

        //新知识点:
        //空合并赋值是C#8.0新增的一个运算符 ??=
        //类似复合赋值
        // 左值 ??= 右值
        // 当左值为空时才会将右值赋值给左值
        // 示例
        str ??= "4565";
        print(str);
        //注意:只有当左值为空时才会将右值赋值,因此不为空的变量不会被改变
        str ??= "1111";
        print(str);
        #endregion

        #region 知识点六 解构函数Deconstruct
        //知识回顾:
        //在之前学习元组的解构时,我们可以通过声明变量来存储元组值
        //相当于把多个返回值元组值存入对应的变量中
        //示例回顾:
        int i;
        float f;
        string s;
        (i,f,_,s) = GetInfo();

        //新知识点:解构函数Deconstruct 在C# 7引入了
        //我们可以自定义类似元组的解构方式
        //这样我们可以将自定义对象的多个属性通过解构方式一次性存入多个变量中
        //语法:
        //类内部需要声明public void Deconstruct(out 类型 参数名, out 类型 参数名.....)
        //特点:
        //一个类中可以有多个Deconstruct方法,只要参数数量不同
        Person p = new Person();
        p.name = "唐老狮";
        p.sex = false;
        p.email = "tpandme@163.com";
        p.number = "123123123123";

        //我们可以对该对象进行元组方式的变量赋值解构
        //相当于把不同的成员变量值存入对应的临时变量中
        (string name, bool sex) = p;
        print(name);
        print(sex);
        string str3;
        (_, _, str3) = p;
        print(str3);
        #endregion
    }

    public (int, float, bool, string) GetInfo()
    {
        return (1, 3.4f, true, "123");
    }

    public int CalcInfo(int i)
    {
        bool b = false;
        i += 10;
        Calc(ref i, ref b);
        return i;

        static void Calc(ref int i, ref bool b)
        {
            i += 10;
            b = true;
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DiscountInfo
{
    public string discount;
    public bool isDiscount;

    public DiscountInfo(string discount, bool isDiscount)
    {
        this.discount = discount;
        this.isDiscount = isDiscount;
    }

    public void Deconstruct(out string dis, out bool isDis)
    {
        dis = this.discount;
        isDis = this.isDiscount;
    }
}

public class Lesson11 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 模式匹配回顾
        //模式匹配(Pattern Matching)
        //"模式匹配"是一种检查表达式是否符合特定模式的方法
        //在本课程中指的是:用已知数据的信息结构
        //通过一些固定语法形式确认模式传递的具体数据的构成

        //目前已学习的模式匹配
        //1.常量模式(is 常量):用于判断变量值是否等于某个值
        object o = 1.5f;
        if (o is 1)
        {
            print("o是1");
        }
        if (o is null)
        {
            print("o是null");
        }
        //2.类型模式(is 类型 变量,case 类型 变量):用于判断变量值类型,并将值转换到同类型变量
        //判断某个对象是否是某个类型,并会将这个对象转换为对应的变量
        if (o is int i)
        {
            print(i);
        }
        switch (o)
        {
            case int value:
                print("int:" + value);
                break;
            case float value:
                print("float:" + value);
                break;
            case null:
                print("null");
                break;
            default:
                break;
        }
        //3.var模式:用于将任意值存储到隐式类型变量
        //          相当于将值装箱到一个自己推断类型的变量
        if (o is var v)
        {
            print(v);
        }
        int kk = GetInt();
        if(kk >= 0 && kk <= 10)
        {

        }

        if (GetInt() is var k && k >= 0 && k <= 10)
        {
            
        }
        #endregion

        #region 知识点二 模式匹配增强特性——switch表达式
        //switch表达式是有返回值的switch语句写法
        //用=>代替case:语法
        //用_元符号代替default
        //使用限制:需要在switch语句充当表达式(只有一个返回结果)时使用
        //语法:
        //返回值 => 参数 switch
        //{
        //模式=>返回值表达式,
        //模式=>返回值表达式,
        //模式=>返回值表达式,
        //....
        //_ => 返回值表达式,
        //}

        print(GetPos(PosType.Bottom_Right));
        #endregion

        #region 知识点三 模式匹配增强特性——属性模式
        //在类型模式的基础上判断对象更具体的属性
        //用法格式: is {属性:值, 属性:值}
        DiscountInfo info = new DiscountInfo("5折", true);
        //if( info.discount == "6折" && info.isDiscount)
        if (info is { discount: "6折", isDiscount: true })
            print("信息相同");

        print(GetMoney(info, 100));

        //该特性可以结合switch表达式使用
        //通过switch可以使用属性模式判断对象属性
        #endregion

        #region 知识点四 模式匹配增强特性——元组模式
        //通过之前学习的属性模式,我们可以在switch表达式中判断对象属性同时返回结果
        //但是如果需要处理多个独立参数,就需要创建数据结构类
        //元组模式可以更简单地实现这个功能,不需要创建数据结构类,直接使用元组进行判断
        int ii = 10;
        bool bb = true;
        if((ii, bb) is (11, true))
        {
            print("元组值相同");
        }
        //示例说明:
        print(GetMoney("5折", true, 200));
        #endregion

        #region 知识点五 模式匹配增强特性——位置模式
        //如果自定义对象实现了Deconstruct解构函数
        //那么可以直接用对应的元组结构进行is判断
        if(info is ("5折", true))
        {
            print("位置模式 匹配成功");
        }

        //同样也可以结合switch表达式处理逻辑
        //示例说明:
        print(GetMoney2(info, 300));

        //扩展:可用when关键字添加逻辑条件
        #endregion
    }

    public int GetInt()
    {
        return 1;
    }

    public float GetMoney(DiscountInfo info, float money) => info switch
    {
        //使用属性模式配合switch表达式判断对象属性
        { discount: "5折", isDiscount: true } => money * .5f,
        { discount: "6折", isDiscount: true } => money * .6f,
        { discount: "7折", isDiscount: true } => money * .7f,
        _ => money
    };

    public float GetMoney2(DiscountInfo info, float money) => info switch
    {
        ("5折", true) when money > 100 => money * .5f,
        ("6折", true) => money * .6f,
        ("7折", true) => money * .7f,
        _ => money
    };

    public float GetMoney3(DiscountInfo info, float money) => info switch
    {
        (string dis, bool isDis) when dis == "5折" && isDis => money * .5f,
        (string dis, bool isDis) when dis == "6折" && isDis => money * .6f,
        (string dis, bool isDis) when dis == "7折" && isDis => money * .7f,
        _ => money
    };

    public float GetMoney(string discount, bool isDiscount, float money) => (discount, isDiscount) switch
    {
        ("5折", true) => money * .5f,
        ("6折", true) => money * .6f,
        ("7折", true) => money * .7f,
        _ => money
    };

    public Vector2 GetPos(PosType type) => type switch
    {
        PosType.Top_Left => new Vector2(0, 0),
        PosType.Top_Right => new Vector2(1, 0),
        PosType.Bottom_Left => new Vector2(0, 1),
        PosType.Bottom_Right => new Vector2(1, 1),
        _ => new Vector2(0, 0)
    };

    // Update is called once per frame
    void Update()
    {
        
    }
}

public enum PosType
{
    Top_Left,
    Top_Right,
    Bottom_Left,
    Bottom_Right,
}

不会做游戏!