[Unity] C#中级编程 - 04 - 泛型/构造函数/ref
Posted L建豪 忄YH
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Unity] C#中级编程 - 04 - 泛型/构造函数/ref相关的知识,希望对你有一定的参考价值。
[Unity中文课堂教程] C#中级编程 - 04 - 泛型/构造函数/ref
原教程视频地址:
《[Unity中文课堂教程预告片] C#中级编程_哔哩哔哩_bilibili》
《C# 泛型(Generic) | 菜鸟教程 (runoob.com)》
《C# 泛型讲解_泛型基础_C# Generic_天马3798-CSDN博客_c#泛型》
内容短小精悍简练,每节只有几分钟。很适合用来预习和复习。
类的构造函数
《C# 类(Class) | 菜鸟教程 (runoob.com)》(构造函数)先补充这个概念,和python的形势不太一样,之前没用到所以忘记了。
- 类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
- 构造函数的名称与类的名称完全相同,它没有任何返回类型。
脚本①:
public class Exercise_4_7 : MonoBehaviour
int num = 0;
static int num_s = 0;
public Exercise_4_7() // 构造函数,无须设返回类型,与类名相同
num_s += 1;
num += 1;
Debug.Log("创建了类对象,调用了构造函数");
public int num_get() // 返回局部属性
return num;
public int nums_get() // 返回静止属性
return num_s;
脚本②:
public class Exercise_4_8 : MonoBehaviour
void Start()
Exercise_4_7 myClass = gameObject.AddComponent<Exercise_4_7>();
Exercise_4_7 myClass_0 = gameObject.AddComponent<Exercise_4_7>();
Debug.Log("num = " + myClass.num_get()); // 局部属性不通用
Debug.Log("nums = " + myClass.nums_get()); // 静止属性通用
// 二者均在创建对象时在构造函数中累加了
ref:按引用传递参数
《ref 关键字 - C# 参考 | Microsoft Docs》菜鸟教程例子中看到了,补充一下。
- 理解为传递指针,传递参数本身,而不是传递参数的值。也就说在内部修改形参就会直接影响修改了实参。
void Method(ref int refArgument) // 若要使用 ref 参数,方法定义和调用方法均必须显式使用 ref 关键字
refArgument = refArgument + 44;
int number = 1; // 传递到 ref 或 in 形参的实参必须先经过初始化,然后才能传递。
Method(ref number); // 显式使用关键字
Console.WriteLine(number);
// Output: 45
- 在c#中还要其他
方法参数
关键字,如params
、in
、out
。这些之后再详述吧。
泛型方法/类
- 传参前,一般需要先规定类型,然后函数内就可对该类型作出针对的操作运算。而c#允许连同类型也设为一个参数,在调用时再设定。这种操作称为泛型。
- 因为类型不确定,所以泛型不能作大部分操作运算,比如加减乘除、方法调用等,会在编译时就报错。基本上常用的是一些赋值或删除空对象的操作。
脚本①:
public class Exercise_4_7 : MonoBehaviour
public void Swap<T>(ref T num_0, ref T num_1)
T num_3; // 创建临时变量,用于交互2个参数的值
num_3 = num_0;
num_0 = num_1;
num_1 = num_3;
// num_1 ++; // 尝试是否可以作针对操作,不可用,会直接报错
Debug.Log("使用泛型方法交互了 "+num_0+" 和 "+num_1+" 的内容");
脚本②:
public class Exercise_4_8 : MonoBehaviour
void Start()
Exercise_4_7 myClass = gameObject.AddComponent<Exercise_4_7>(); //其实这就是泛型类
int num_0 = 1,num_1 = 2;
myClass.Swap<int>(ref num_0, ref num_1); // 调用普通类中的泛型方法
- 一般为了方便调用,应该将该泛型方法设为静态。这就可省去创建对象一步了。
- 泛型除了创建方法或类外,还能创建泛型接口、泛型事件和泛型委托,这里暂不细说。
泛型约束
- 在声明泛型方法和泛型类的时候,都可以给泛型加上一定的约束来满足我们特定的一些条件。
public class CacheHelper<T> where T:new()
使用关键字where。 下面列出了6中类型的约束
- where T: struct
类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。有关更多信息,请参见使用可以为 null 的类型(C# 编程指南)。- where T : class
类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。- where T:new()
类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。- where T:<基类名>
类型参数必须是指定的基类或派生自指定的基类。- where T:<接口名称>
类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。- where T:U
为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。
- 泛型类和泛型方法差不多,在实例化时会需要在尖括号内输入类型。其实在unity中早有用过泛型类,比如上面例子中,实例化 “继承了
MonoBehaviour
的类” 时用到的方法。
应用例子
在之前学习麦扣的教程时,第一次接触到泛型的用法。当时看不懂其作用,现在再看,个人认为是打包创建静态类的过程。下面贴出全部代码,以示参考学习。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T:Singleton<T> // 约束只能是类,且只能是继承了该泛型类的类。
private static T instance;
public static T Instance // 设置参数只可读,
get
return instance;
// 实例化
protected virtual void Awake() // protected 关键字代表只能子类访问
// virtual 关键字代表子类能复写该方法
if (instance != null)
Destroy(gameObject); // 如果静态类存在就删除
else // 好奇这里是不是不应该有else,当时弹幕也疑惑。
instance = (T)this; // 从新获取静态类
// 判断是否已实例化
public static bool IsInitialized // 同上
get
return instance != null; // 使用get关键字的巧妙,函数都省略,直接写在这里。
// 清空实例化
protected virtual void OnDestroy() // 关键字同上
if(instance == this)
instance = null;
以上是关于[Unity] C#中级编程 - 04 - 泛型/构造函数/ref的主要内容,如果未能解决你的问题,请参考以下文章