14.静态本地函数、using、??=和解构函数Deconstruct

14.CSharp各版本新功能和语法-CSharp8功能和语法-Using空合并赋值静态本地解构


14.1 知识点

C#8对应的Unity版本

  • Unity 2020.3 —— C# 8
  • 但是部分新内容还不在该版本Unity中被支持
  • 筛选了一些比较实用的内容给大家讲解

C#8的新增功能和语法有哪些

  1. Using 声明
  2. 静态本地函数
  3. Null 合并赋值
  4. 解构函数Deconstruct
  5. 模式匹配增强功能

静态本地函数

  • 知识回顾:
    • 在C#7的新语法中我们学习了本地函数
    • 本地函数知识回顾
      • 基本概念:在函数内部声明一个临时函数
      • 注意:
        • 本地函数只能在声明该函数的函数内部使用
        • 本地函数可以使用声明自己的函数中的变量
      • 作用:方便逻辑的封装
      • 建议:把本地函数写在主要逻辑的后面,方便代码的查看
  • 新知识点:
    • 静态本地函数就是在本地函数前方加入static静态关键字
    • 它的作用就是让本地函数不能够使用访问封闭范围内(也就是上层方法中)的任何变量
    • 作用:让本地函数只能处理逻辑,避免让它通过直接改变上层变量来处理逻辑造成逻辑混乱
public int CalcInfo(int i)
{
    string str;
    bool b = false;
    i += 10;
    Calc(ref i, ref b);
    return i;

    //要改变上层语句块变量 可以使用ref修饰参数传进来
    static void Calc(ref int i, ref bool b)
    {
        //str = "123";//报错 静态本地函数不能使用上一层语句块的变量
        i += 10;
        b = true;
    }
}

print(CalcInfo(10));

Using 声明

  • 知识回顾:
    • 在数据持久化xml相关知识当中
    • 我们学习了using相关的知识点
    • using(对象声明)
      • 使用对象,语句块结束后 对象将被释放掉
      • 当语句块结束 会自动帮助我们调用 对象的 Dispose这个方法 让其进行销毁
      • using一般都是配合 内存占用比较大 或者 有读写操作时 进行使用的
  • 新知识点:
    • using 声明就是对using()语法的简写
    • 当函数执行完毕时 会自动调用对象的Dispose方法 释放对象
//举例回顾:
using (StreamWriter streamWriter1 = new StreamWriter("文件路径"))
{
    //对该变量进行逻辑处理 该变量只能在这个语句块中使用
    streamWriter1.Write(true);
    streamWriter1.Write(1.2f);
    streamWriter1.Flush();
    streamWriter1.Close();
}
//语句块结束执行时 自动调用 声明对象的 Dispose方法 释放对象

//新知识点:
//using 声明就是对using()语法的简写
//当函数当前语句块执行完毕时 会自动调用对象 Dispose方法 释放对象

using StreamWriter streamWriter2 = new StreamWriter("文件路径");
//对该对象进行逻辑操作
streamWriter2.Write(5);
streamWriter2.Flush();
streamWriter2.Close();
//利用这个写法 就会在上层语句块执行结束时释放该对象

//注意:在使用using语法时,声明的对象必须继承System.IDisposable接口
public class TestUsing : IDisposable
{
    public void Dispose()
    {
        
    }
}

//因为必须具备Dispose方法,所以当声明没有继承该接口的对象使用using时会报错
using TestUsing t = new TestUsing();

Null合并赋值??=

  • 知识回顾:
    • 在C#进阶的特殊语法知识点中我们学习了 ?? 空合并操作符
    • 回顾空合并操作符知识点
      • 左边值 ?? 右边值
      • 如果左边值为null 就返回右边值 否则返回左边值
      • 只要是可以为null的类型都能用
    • 举例:
      string str = null;
      string str2 = str ?? "234";
      print(str2);//234
      
  • 新知识点:
    • 空合并赋值是C#8.0新加的一个运算符 ??=
    • 类似复合运算符
    • 左边值 ??= 右边值
    • 当左侧为空时才会把右侧值赋值给变量
    • 举例:
      str ??= "4565";
      print(str);//4565
      // 注意:由于左侧为空才会讲右侧赋值给变量,所以不为空的变量不会改变
      str ??= "1111";
      print(str);//4565
      

解构函数Deconstruct

  • 知识回顾:
    • 我们之前学习过元组的解构,就是可以用单独的变量存储元组的值
    • 相当于把多返回值元组拆分到不同的变量中
public (int, float, bool, string) GetInfo()
{
    return (1, 3.4f, true, "123");
}

// 举例回顾:
int i;
float f;
string s;
(i,f,_,s) = GetInfo();
  • 新知识点:解构函数Deconstruct (C# 7就有了)
    • 我们可以在自定义类当中声明解构函数
    • 声明后我们,可以将该自定义类对象利用元组的写法,直接进行变量的获取
    • 语法:在类的内部申明函数public void Deconstruct(out 变量类型 变量名, out 变量类型 变量名…..)
    • 特点:一个类中可以有多个Deconstruct,但是参数数量不能相同
/// <summary>
/// 表示一个人的类
/// </summary>
public class Person
{
    // 姓名
    public string name;

    // 性别
    public bool sex;

    // 联系电话
    public string number;

    // 电子邮件
    public string email;

    /// <summary>
    /// 从 Person 对象中获取姓名和性别
    /// </summary>
    /// <param name="n">输出参数,存储姓名</param>
    /// <param name="sex">输出参数,存储性别</param>
    public void Deconstruct(out string n, out bool sex) => (n, sex) = (this.name, this.sex);

    /// <summary>
    /// 从 Person 对象中获取姓名、性别和联系电话
    /// </summary>
    /// <param name="n">输出参数,存储姓名</param>
    /// <param name="sex">输出参数,存储性别</param>
    /// <param name="number">输出参数,存储联系电话</param>
    public void Deconstruct(out string n, out bool sex, out string number) => (n, sex, number) = (this.name, this.sex, this.number);

    /// <summary>
    /// 从 Person 对象中获取姓名、性别、联系电话和电子邮件
    /// </summary>
    /// <param name="n">输出参数,存储姓名</param>
    /// <param name="sex">输出参数,存储性别</param>
    /// <param name="number">输出参数,存储联系电话</param>
    /// <param name="email">输出参数,存储电子邮件</param>
    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;
    }
}


// 举例:
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);//False
string str3;
(_, _, str3) = p;
print(str3);//123123123123

14.2 知识点代码

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

#region 知识点四 Using 声明

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

#endregion

#region 知识点六 解构函数Deconstruct

/// <summary>
/// 表示一个人的类
/// </summary>
public class Person
{
    // 姓名
    public string name;

    // 性别
    public bool sex;

    // 联系电话
    public string number;

    // 电子邮件
    public string email;

    /// <summary>
    /// 从 Person 对象中获取姓名和性别
    /// </summary>
    /// <param name="n">输出参数,存储姓名</param>
    /// <param name="sex">输出参数,存储性别</param>
    public void Deconstruct(out string n, out bool sex) => (n, sex) = (this.name, this.sex);

    /// <summary>
    /// 从 Person 对象中获取姓名、性别和联系电话
    /// </summary>
    /// <param name="n">输出参数,存储姓名</param>
    /// <param name="sex">输出参数,存储性别</param>
    /// <param name="number">输出参数,存储联系电话</param>
    public void Deconstruct(out string n, out bool sex, out string number) => (n, sex, number) = (this.name, this.sex, this.number);

    /// <summary>
    /// 从 Person 对象中获取姓名、性别、联系电话和电子邮件
    /// </summary>
    /// <param name="n">输出参数,存储姓名</param>
    /// <param name="sex">输出参数,存储性别</param>
    /// <param name="number">输出参数,存储联系电话</param>
    /// <param name="email">输出参数,存储电子邮件</param>
    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;
    }
}


#endregion

public class Lesson14_CSharp各版本新功能和语法_CSharp8功能和语法_Using声明空合并赋值静态本地函数解构函数 : MonoBehaviour
{
    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的新语法中我们学习了本地函数
        //本地函数知识回顾
        //基本概念:在函数内部声明一个临时函数
        //注意:
        //本地函数只能在声明该函数的函数内部使用
        //本地函数可以使用声明自己的函数中的变量
        //作用:方便逻辑的封装
        //建议:把本地函数写在主要逻辑的后面,方便代码的查看


        //新知识点:
        //静态本地函数就是在本地函数前方加入static静态关键字
        //它的作用就是让本地函数不能够使用访问封闭范围内(也就是上层方法中)的任何变量
        //作用 让本地函数只能处理逻辑,避免让它通过直接改变上层变量来处理逻辑造成逻辑混乱

        print(CalcInfo(10));
        #endregion

        #region 知识点四 Using 声明

        //知识回顾:
        //在数据持久化xml相关知识当中
        //我们学习了using相关的知识点
        //using(对象声明)
        //{
        //使用对象,语句块结束后 对象将被释放掉
        //当语句块结束 会自动帮助我们调用 对象的 Dispose这个方法 让其进行销毁
        //using一般都是配合 内存占用比较大 或者 有读写操作时  进行使用的 
        //}

        //举例回顾:
        using (StreamWriter streamWriter1 = new StreamWriter("文件路径"))
        {
            //对该变量进行逻辑处理 该变量只能在这个语句块中使用
            streamWriter1.Write(true);
            streamWriter1.Write(1.2f);
            streamWriter1.Flush();
            streamWriter1.Close();
        }
        //语句块结束执行时 调用 声明对象的 Dispose方法 释放对象

        //新知识点:
        //using 声明就是对using()语法的简写
        //当函数执行完毕时 会调用 对象的 Dispose方法 释放对象

        using StreamWriter streamWriter2 = new StreamWriter("文件路径");
        //对该对象进行逻辑操作
        streamWriter2.Write(5);
        streamWriter2.Flush();
        streamWriter2.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);//234

        //新知识点:
        //空合并赋值是C#8.0新加的一个运算符 ??=
        //类似复合运算符
        // 左边值 ??= 右边值
        // 当左侧为空时才会把右侧值赋值给变量

        // 举例:
        str ??= "4565";
        print(str);//4565
        //注意:由于左侧为空才会讲右侧赋值给变量,所以不为空的变量不会改变
        str ??= "1111";
        print(str);//4565

        #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);//False
        string str3;
        (_, _, str3) = p;
        print(str3);//123123123123

        #endregion

    }

    #region 知识点六 解构函数Deconstruct

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

    #endregion

    #region 知识点三 静态本地函数

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

        //要改变上层语句块变量 可以使用ref修饰参数传进来
        static void Calc(ref int i, ref bool b)
        {
            //str = "123";//报错 静态本地函数不能使用上一层语句块的变量
            i += 10;
            b = true;
        }
    }

    #endregion
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏