7.命名参数、可选参数和动态类型

7.CSharp各版本新功能和语法-CSharp1-4功能和语法


7.1 知识点

最低支持的C#版本

  • 只要是Unity 5.5及以上的版本
  • 就支持C# 4版本

C# 1~4的功能和语法有哪些?

  • 注意:在这里不会提及所有的内容
  • 主要会提及Unity开发中会用到的一些功能和特性
  • 对于一些不适合在Unity中使用的内容我会省略

C# 1

  • 委托、事件(C#进阶套课)

C# 2

  • 泛型、匿名方法、迭代器、可空类型(C#进阶套课)

C# 3

  • 隐式类型、对象集合初始化、Lambda表达式、匿名类型(C#进阶套课)
  • 自动实现属性、拓展方法、分部类(C#核心套课)
  • Linq相关的表达式树(以后专门讲)

C# 4

  • 泛型的协变和逆变(C#进阶套课)
  • 命名和可选参数
  • 动态类型

命名参数和可选参数

命名参数和可选参数让我们可以不用匹配参数在所调用方法中的顺序
好处:可以让我们更方便的调用函数,少写一些重载函数

public void Test(int i, float f, bool b)
{

}

public void Test2(int i , bool b = true, string s = "123")
{

}

//有了命名参数,我们将不用匹配参数在所调用方法中的顺序
//每个参数可以按照参数名字进行指定
Test(1, 1.2f, true);
Test(f: 3.3f, i: 5, b: false);
Test(b: false, f: 3.4f, i: 3);

//命名参数可以配合可选参数使用,让我们做到跳过其中的默认参数直接赋值后面的默认参数
Test2(1, true, "234");
Test2(1, s: "234");

动态类型

关键词:dynamic
作用:通过dynamic类型标识变量的使用和对其成员的引用绕过编译时类型检查,改为在运行时解析这些操作。在大多数情况下,dynamic类型和object类型行为类似,任何非Null表达式都可以转换为dynamic类型。dynamic类型和object类型不同之处在于,编译器不会对包含类型 dynamic 的表达式的操作进行解析或类型检查,而是将有关该操作的信息打包在一起,然后在运行时评估操作。在此过程中,dynamic类型的变量会编译为object类型的变量。

注意:

  1. 使用dynamic功能需要将Unity的.Net API兼容级别切换为.Net 4.x。
  2. IL2CPP 不支持 C# dynamic 关键字,因为它需要 JIT 即时编译,而 IL2CPP 无法实现。在打包时需要将脚本运行环境设置为 Mono。
  3. 动态类型是无法自动补全方法的,因此在书写时一定要保证方法的拼写正确性。因此,该功能只建议了解,不建议大家使用。

好处:

  1. 动态类型可以节约代码量,当不确定对象类型,但是确定对象成员时,可以使用动态类型
  2. 通过反射处理某些功能时,也可以考虑使用动态类型来替换它

举例说明:

public class Test1
{
    public void TestTest()
    {

    }
}

public class Test2
{
    public void TestTest()
    {

    }
}


dynamic dyn = 1;
object obj = 2;

dyn += 2;

print(obj.GetType());//System.Int32
print(dyn.GetType());//System.Int32
print(dyn);//3

object t = new Test1();
dynamic tmp = t;
tmp.TestTest();

其他使用动态类型的情况:

与 COM 对象交互:当需要与 COM(Component Object Model)对象进行交互时,通常需要使用动态类型,因为 COM 对象的类型信息不是在编译时可用的。

dynamic comObject = GetCOMObject(); // 获取 COM 对象
comObject.Method(); // 使用 COM 对象的方法

处理反射操作:当需要使用反射来动态地调用类型的成员时,动态类型也很有用。

dynamic obj = Activator.CreateInstance(type); // 根据类型创建实例
obj.SomeMethod(); // 调用类型的方法

与动态语言交互:当需要与其他动态语言(如Python或JavaScript)交互时,动态类型可以简化类型转换。

dynamic pythonObject = PythonEngine.Execute("some_python_code.py"); // 执行 Python 代码
var result = pythonObject.SomeFunction(); // 调用 Python 对象的函数

处理动态数据:有时候,从外部系统或者网络接口获取的数据类型在编译时不可知,此时动态类型可以帮助处理这种情况。

dynamic data = GetDataFromExternalSource(); // 从外部获取数据
Console.WriteLine(data.SomeProperty); // 访问数据的属性

过度使用动态类型可能会使代码变得难以理解和维护,因为编译器无法提供类型检查和自动完成等功能。因此,应该根据情况慎重使用动态类型。

总结

  • C# 1~4版本中的功能和语法
  • 大多数我们已经在C#四部曲中学习完毕
  • 命名和可选参数可以帮助我们少写一些重载函数
  • 动态类型可以让我们在某些情况下节约代码量
  • 但是由于要使用.Net 4.x,并且IL2CPP不支持,所以不建议使用它,但是如果有特殊需求不得不用,那我们只有退而求其次

7.2 知识点代码

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


#region 知识点四 补充未讲解的内容 动态类型

public class Test1
{
    public void TestTest()
    {

    }
}

public class Test2
{
    public void TestTest()
    {

    }
}

#endregion

public class Lesson07_CSharp各版本新功能和语法_CSharp1_4功能和语法 : MonoBehaviour
{    
    void Start()
    {
        #region 知识点一 最低支持的C#版本
        //只要是Unity 5.5及以上的版本
        //就支持C# 4版本
        #endregion

        #region 知识点二 C# 1~4的功能和语法有哪些?
        //注意:在这里我不会提及所有的内容
        //     主要会提及Unity开发中会用到的一些功能和特性
        //     对于一些不适合在Unity中使用的内容我会省略

        //C# 1 —— 委托、事件(C#进阶套课)
        //C# 2 —— 泛型、匿名方法、迭代器、可空类型(C#进阶套课)
        //C# 3 ——
        //隐式类型、对象集合初始化、Lambda表达式、匿名类型(C#进阶套课)
        //自动实现属性、拓展方法、分部类(C#核心套课)
        //Linq相关的表达式树(以后专门讲)
        //C# 4 ——
        //泛型的协变和逆变(C#进阶套课)
        //命名和可选参数
        //动态类型
        #endregion

        #region 知识点三 补充未讲解全面的内容 命名和可选参数
        //有了命名参数,我们将不用匹配参数在所调用方法中的顺序
        //每个参数可以按照参数名字进行指定
        Test(1, 1.2f, true);
        Test(f: 3.3f, i: 5, b: false);
        Test(b: false, f: 3.4f, i: 3);

        //命名参数可以配合可选参数使用,让我们做到跳过其中的默认参数直接赋值后面的默认参数
        Test2(1, true, "234");
        Test2(1, s: "234");

        //好处:可以让我们更方便的调用函数,少写一些重载函数
        #endregion

        #region 知识点四 补充未讲解的内容 动态类型

        //关键词:dynamic
        //作用:通过dynamic类型标识变量的使用和对其成员的引用绕过编译时类型检查
        //     改为在运行时解析这些操作。
        //     在大多数情况下,dynamic类型和object类型行为类似
        //     任何非Null表达式都可以转换为dynamic类型。
        //     dynamic类型和object类型不同之处在于,
        //     编译器不会对包含类型 dynamic 的表达式的操作进行解析或类型检查
        //     编译器将有关该操作信息打包在一起,之后这些信息会用于在运行时评估操作。
        //     在此过程中,dynamic 类型的变量会编译为 object 类型的变量。
        //     因此,dynamic 类型只在编译时存在,在运行时则不存在。

        //注意:1.使用dynamic功能 需要将Unity的.Net API兼容级别切换为.Net 4.x
        //     2.IL2CPP 不支持 C# dynamic 关键字。它需要 JIT 即时编译,而 IL2CPP 无法实现 。打包时要改成Mono。
        //     3.动态类型是无法自动补全方法的,我们在书写时一定要保证方法的拼写正确性
        //        所以该功能我们只做了解,不建议大家使用

        //举例说明:
        dynamic dyn = 1;
        object obj = 2;

        dyn += 2;

        print(obj.GetType());//System.Int32
        print(dyn.GetType());//System.Int32
        print(dyn);//3

        object t = new Test1();
        dynamic tmp = t;
        tmp.TestTest();

        //好处:动态类型可以节约代码量,当不确定对象类型,但是确定对象成员时,可以使用动态类型
        //     通过反射处理某些功能时,也可以考虑使用动态类型来替换它

        #endregion

        #region 总结
        //C# 1~4版本中的功能和语法
        //大多数我们已经在C#四部曲中学习完毕
        //命名和可选参数可以帮助我们少写一些重载函数
        //动态类型可以让我们在某些情况下节约代码量
        //但是由于要使用.Net 4.x,并且IL2CPP不支持,所以不建议使用它,但是如果有特殊需求不得不用,那我们只有退而求其次
        #endregion
    }

    #region 知识点三 补充未讲解全面的内容 命名和可选参数

    public void Test(int i, float f, bool b)
    {

    }

    public void Test2(int i , bool b = true, string s = "123")
    {

    }

    #endregion
}

7.3 练习题

在Unity中使用 dynamic 动态关键字时,需要注意什么?

使用dynamic功能需要注意以下几点:

  • 切换Unity的.Net API兼容级别为.Net 4.x,以支持dynamic关键字的使用。
  • IL2CPP 不支持 C# dynamic 关键字。dynamic需要 JIT 编译,而 IL2CPP 是AOT无法实现。
  • 动态类型是无法自动补全方法的,因此在书写时一定要保证方法的拼写正确性。


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

×

喜欢就点赞,疼爱就打赏