IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> [Unity] C#中级编程 - 04 - 泛型/构造函数/ref -> 正文阅读

[游戏开发][Unity] C#中级编程 - 04 - 泛型/构造函数/ref

[Unity中文课堂教程] C#中级编程 - 04 - 泛型/构造函数/ref

原教程视频地址:

《[Unity中文课堂教程预告片] C#中级编程_哔哩哔哩_bilibili

C#中级编程 - Unity中文课堂 (u3d.cn)

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#中还要其他方法参数关键字,如paramsinout。这些之后再详述吧。

泛型方法/类

  • 传参前,一般需要先规定类型,然后函数内就可对该类型作出针对的操作运算。而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中类型的约束

    1. where T: struct
      类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。有关更多信息,请参见使用可以为 null 的类型(C# 编程指南)。
    2. where T : class
      类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
    3. where T:new()
      类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。
    4. where T:<基类名>
      类型参数必须是指定的基类或派生自指定的基类。
    5. where T:<接口名称>
      类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
    6. where T:U
      为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。

    C# 泛型讲解_泛型基础_C# Generic_天马3798-CSDN博客_c#泛型

  • 泛型类和泛型方法差不多,在实例化时会需要在尖括号内输入类型。其实在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;
		}
	}
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 16:03:21  更:2021-12-11 16:04:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 21:51:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码