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

public struct TestRef
{
    public int atk;
    public int def;

    public TestRef(int atk, int def)
    {
        this.atk = atk;
        this.def = def;
    }
}

public class Lesson8 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 C#7对应的Unity版本
        //Unity 2018.3支持C# 7 
        //Unity 2019.4支持C# 7.3 
        //7.1, 7.2, 7.3相关内容都是基于 7的一些改进
        #endregion

        #region 知识点二 C#7的新增功能和语法有哪些
        //1.字面值改进
        //2.out 参数相关 和 弃元知识点
        //3.ref 返回值
        //4.本地函数

        //5.抛出表达式
        //6.元组
        //7.模式匹配
        #endregion

        #region 知识点三 字面值改进
        //基本概念:在声明数值变量时,为了方便查看数值
        //         可以在数值之间插入_作为分隔符
        //主要作用:方便数值变量的阅读
        int i = 9_9123_1239;
        print(i);
        int i2 = 0xAB_CD_17;
        print(i2);
        #endregion

        #region 知识点四 out变量的快捷使用 和 弃元
        //用法:不需要再使用带有out参数的函数之前,声明对应变量
        //作用:简化代码,提高开发效率

        //1.以前使用带out函数的写法
        //int a;
        //int b;
        //Calc(out a, out b);

        //2.现在的写法
        Calc(out int x, out int y);
        print(x);
        print(y);

        //3.结合var类型更简便(但是这种写法在存在重载时不能正常使用,必须明确调用的是谁)
        Calc(out int a, out var b);
        print(a);
        print(b);

        //4.可以使用 _弃元符号 省略不想使用的参数

        Calc(out int c, out _);
        print(c);
        #endregion

        #region 知识点五 ref修饰临时变量和返回值
        //基本概念:使用ref修饰临时变量和函数返回值,可以让赋值变为引用传递
        //作用:用于修改数据对象中的某些值类型变量
        //1.修饰值类型临时变量
        int testI = 100;
        ref int testI2 = ref testI;
        testI2 = 900;
        print(testI);

        TestRef r = new TestRef(5,5);
        ref TestRef r2 = ref r;
        r2.atk = 10;
        print(r.atk);

        //2.获取对象中的参数
        ref int atk = ref r.atk;
        atk = 99;
        print(r.atk);

        //3.函数返回值
        int[] numbers = new int[] { 1, 2, 3, 45, 5, 65, 4532, 12 };
        ref int number = ref FindNumber(numbers, 5);
        number = 98765;
        print(numbers[4]);
        #endregion

        #region 知识点六 本地函数
        //基本概念:在函数内部声明一个临时函数
        //注意:
        //本地函数只能在声明该函数的函数内部使用
        //本地函数可以使用声明自己的函数中的变量
        //作用:方便逻辑的封装
        //建议:把本地函数写在主要逻辑的后面,方便代码的查看

        print(TestTst(10));
        #endregion

        #region 总结
        //C#7的新语法更新重点主要是 代码简化
        //今天学习的out和ref新用法,弃元、本地函数都是相对比较重要的内容
        //可以给我们带来很多便捷性
        #endregion
    }

    public int TestTst(int i)
    {
        bool b = false;
        i += 10;
        Calc();
        print(b);
        return i;

        void Calc()
        {
            i += 10;
            b = true;
        }
    }

    public ref int FindNumber(int[] numbers, int number)
    {
        for (int i = 0; i < numbers.Length; i++)
        {
            if (numbers[i] == number)
                return ref numbers[i];
        }
        return ref numbers[0];
    }

    public void Calc(out int a, out int b)
    {
        a = 10;
        b = 20;
    }

    public void Calc(out float a, out float b)
    {
        a = 10;
        b = 20;
    }

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

public class Lesson9 : MonoBehaviour
{
    public (int, float) yz;

    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 抛出异常
        // throw 知识回顾
        // 抛出异常表达式用于主动抛出一个异常
        // 一般使用方式:throw + new一个异常对象

        // 异常类:Exception

        // throw new NullReferenceException("1231231");

        #region C# 内置异常
        // 常见异常类型:
        // IndexOutOfRangeException:当数组下标越界时抛出
        // NullReferenceException:当访问空对象时抛出
        // ArgumentException:参数非法
        // ArgumentNullException:传递了空参数
        // ArgumentOutOfRangeException:参数值超出范围
        // SystemException:系统级异常基类
        // OutOfMemoryException:内存不足
        // StackOverflowException:栈溢出

        // ArithmeticException:算术运算错误
        // ArrayTypeMismatchException:数组类型不匹配
        // BadImageFormatException:图像格式错误
        // DivideByZeroException:除以零错误
        // DllNotFoundException:找不到DLL文件
        // FormatException:格式错误
        // InvalidCastException:无效的类型转换
        // InvalidOperationException:操作在当前状态下无效
        // MethodAccessException:访问权限不足
        // MissingMemberException:缺少成员
        // NotFiniteNumberException:非有限数值
        // NotSupportedException:不支持的操作
        // InvalidOperationException:对象状态无效时调用方法
        #endregion

        // 在C# 7中,可以在更多表达式中进行异常抛出
        // 优点:简化代码

        // 1. 空合并运算符中使用throw
        // InitInfo("123");
        // 2. 条件运算符中使用throw
        // GetInfo("1,2,3", 4);
        // 3. =>符号函数直接throw
        // Action action = () => throw new Exception("出错了,准备接受纪委调查");
        // action();
        #endregion

        #region 知识点二 元组
        // 核心作用:值的集合,提供快速创建数据结构的方式
        //         常用于函数需要返回多个值时,语法:(返回值1类型, 返回值2类型, ...) 
        //         函数内部返回时使用 (返回值1, 返回值2, ...) 

        // 1. 无命名元组声明(通过ItemN访问)
        (int, float, bool, string) yz = (1, 5.5f, true, "123");
        print(yz.Item1);
        print(yz.Item2);
        print(yz.Item3);
        print(yz.Item4);
        
        // 2. 具名元组声明
        (int i, float f, bool b, string str) yz2 = (1, 5.5f, true, "123");
        print(yz2.i);
        print(yz2.f);
        print(yz2.b);
        print(yz2.str);

        // 3. 元组支持==和!=比较
        //    按顺序比较每个成员,全部相等则返回true
        if (yz == yz2)
            print("相等");
        else
            print("不相等");

        // 元组不能作为字段类型,但成员可以访问
        // print(this.yz.Item1);

        #region 元组应用:多返回值
        // 无命名方式接收返回值
        var info = GetInfo();
        print(info.Item1);
        print(info.Item2);
        print(info.Item3);
        
        // 具名方式
        print(info.f);
        print(info.i);
        print(info.str);

        // 元组解构赋值
        int myInt;
        string myStr;
        float myFloat;
        (myStr, myInt, myFloat) = GetInfo();
        // 或直接声明类型
        // (string myStr, int myInt, float myFloat) = GetInfo();
        print(myStr);
        print(myInt);
        print(myFloat);

        // 忽略部分返回值
        (string ss, _, _) = GetInfo();
        print(ss);
        #endregion

        #region 元组应用:字典键
        // 使用元组作为复合键
        Dictionary<(int i, float f), string> dic = new Dictionary<(int i, float f), string>();
        dic.Add((1, 2.5f), "123");

        if(dic.ContainsKey((1, 2.5f)))
        {
            print("存在相同键");
            print(dic[(1, 2.5f)]);
        }
        #endregion
        #endregion

        #region 知识点三 模式匹配
        // 核心作用:通过语法元素检测值是否符合某种模式,并提取信息
        //         在C#7中增强:
        //         1. is表达式增强
        //         2. switch语句的case模式
        // 优点:简化类型检查和值提取

        // 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(o);
        }
        #endregion

        #region 总结
        // 元组和模式匹配是C#7的重要特性
        // 可提高代码效率和简洁性
        // 建议多加练习
        #endregion
    }

    private (string str, int i, float f) GetInfo()
    {
        return ("123", 2, 5.5f);
    }

    private string jsonStr;
    private void InitInfo(string str) => jsonStr = str ?? throw new ArgumentNullException(nameof(str));

    private string GetInfo(string str, int index)
    {
        string[] strs = str.Split(',');
        return strs.Length > index ? strs[index] : throw new IndexOutOfRangeException();
    }

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

不会做游戏!