文章目录

        • 一、概述
        • 二、命名和可选参数
        • 三、动态类型 dynamic

​ 注意:在此仅提及 Unity 开发中会用到的一些功能和特性,对于不适合在 Unity 中使用的内容会忽略。

一、概述

  • C# 1(C# 进阶内容)
    • 委托
    • 事件
  • C# 2(C# 进阶内容)
    • 泛型
    • 匿名方法
    • 迭代器
    • 可空类型
  • C# 3
    • 隐式类型(C# 进阶内容)
    • 对象集合初始化(C# 进阶内容)
    • Lambda 表达式(C# 进阶内容)
    • 匿名类型(C# 进阶内容)
    • 自动实现属性(C# 核心内容)
    • 拓展方法(C# 核心内容)
    • 分部类(C# 核心内容)
  • C# 4
    • 泛型的协变和逆变(C# 进阶内容)
    • 命名和可选参数
    • 动态类型 dynamic

二、命名和可选参数

(一)命名参数

​ 有了命名实参,你将不再需要将实参的顺序与所调用方法的形参列表中的形参顺序相匹配。 每个形参的实参都可按形参名称进行指定。

​ 例如,对于如下函数定义:

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

​ 可以通过以函数定义的顺序按位置发送实参:

Test(1, 1.2f, true);Test(f: 3.3f, i: 5, b: false); // 指定命名参数Test(b: false, f: 3.4f, i: 3); // 任意顺序传参

(二)可选参数

​ 方法、构造函数、索引器或委托的定义可以指定其形参为必需还是可选。任何调用都必须为所有必需的形参提供实参,但可以为可选的形参省略实参。

​ 每个可选形参都有一个默认值作为其定义的一部分。如果没有为该形参发送实参,则使用默认值。 默认值必须是以下类型的表达式之一:

  • 常量表达式;

  • new ValType() 形式的表达式,其中 ValType 是值类型,例如 enum 或 struct;

  • default(ValType) 形式的表达式,其中 ValType 是值类型。

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

​ 可选参数定义于参数列表的末尾和必需参数之后。 如果调用方为一系列可选形参中的任意一个形参提供了实参,则它必须为前面的所有可选形参提供实参。 实参列表中不支持使用逗号分隔的间隔。例如,在以下代码中,使用一个必选形参和两个可选形参定义实例方法。

Test2(1);// 正确,等价于 Test2(1, true, "123");Test2(1, , "234"); // 错误Test2(1, true, "234"); // 正确

(三)结合使用

​ 如果知道第三个形参的名称,则可以使用命名实参来完成此任务:

Test2(1, s: "234");

(四)代码示例

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Lesson3 : MonoBehaviour{// Start is called before the first frame updatevoid Start(){// 有了命名参数,我们将不用匹配参数在所调用方法中的顺序// 每个参数可以按照参数名字进行指定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");}public void Test(int i, float f, bool b) { }public void Test2(int i , bool b = true, string s = "123") { }}

三、动态类型 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 无法实现。
  3. 动态类型是无法自动补全方法的,在书写时要保证方法的拼写正确性。
    该功能只做了解,不建议使用

代码示例:

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Test1{public void TestTest() { }}public class Lesson3 : MonoBehaviour{// Start is called before the first frame updatevoid Start(){dynamic dyn = 1;object obj = 2;dyn += 2;print(obj.GetType()); // System.Int32print(dyn.GetType()); // System.Int32print(dyn); // 3object t = new Test1();dynamic tmp = t; // 直接赋值tmp.TestTest();// 只要能够确定对象内容,直接调用其方法即可}}