Unity 基础 之 List 作为参数传递的值变化的三种情况注意
目录
Unity 基础 之 List 作为参数传递的值变化的三种情况注意
一、简单介绍
二、基本概念
三、三点注意
四、代码示例说明三点注意
1、测试代码
2、运行结果
一、简单介绍
Unity中的一些基础知识点。
本片介绍 List 在作为 参数传递的时候的一些之变化情况。
二、基本概念
所属命名空间:System.Collections.Generic
public class List : IList, ICollection, IEnumerable, IList, ICollection, IEnumerable
List类是 ArrayList 类的泛型等效类。该类使用大小可按需动态增加的数组实现 IList 泛型接口。
泛型的好处: 它为使用c#语言编写面向对象程序增加了极大的效力和灵活性。不会强行对值类型进行装箱和拆箱,或对引用类型进行向下强制类型转换,所以性能得到提高。
三、三点注意
1)list类型是引用类型
2)引用本身是类似于一个“保存地址的值变量”
所以从方法外部传入引用到方法里,那么其实引用本身是复制了一份副本来给方法里使用的,只是说这个复制的引用副本和之前的引用的内容(也就是所指向的对象内存地址)是一样的,所以通过引用操作对象的数据时,可以看到2个引用都操作的同一个对象;但如果你是修改了引用副本本身的值内容(将该引用指向了一个新的对象的内存地址),那么是不会影响到之前方法外的那个引用的,所以修改后会发现2个引用所指向的对象不同了
3)而如果对象引用参数前加上了ref,那么方法参数所传递的不再是引用的副本,而是引用的地址了(即通过引用的地址找到引用,再读出引用里保存的内存地址值,再根据则个地址值去找到真正要操作的对象),所以如果此时你再修改这个引用的值时,会根据引用的地址找到方法外的那个引用,然后修改其内容,所以会发现方法外的引用也会指向新的对象了
四、代码示例说明三点注意
1、测试代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test_List : MonoBehaviour
{
List<string> list_1 = null;
List<string> list_2 = null;
List<string> list_ref_3 = null;
// Start is called before the first frame update
void Start()
{
list_1 = new List<string>();
list_2 = new List<string>();
list_ref_3 = new List<string>();
List<string> copy_ref = list_ref_3; // 复制一个引用
ModifyList_1(list_1);
ModifyList_2(list_2);
ModifyList_ref_3(ref list_ref_3);
Debug.Log("list_1.Count: " + list_1.Count); // 3
Debug.Log("list_2.Count: " + list_2.Count); // 0
// list这个引用已经在ModifyList方法里被修改了,指向的是在ModifyList方法里新new出来的对象了
Debug.Log("list_ref_3.Count: " + list_ref_3.Count); // 3
// 复制的这个引用仍然指向原来最早的那个List
Debug.Log("copy_ref.Count: " + copy_ref.Count); //0
}
// 1)list类型是引用类型
private void ModifyList_1(List<string> list)
{
// 这里的list其实已经是一个引用副本了,但是所指向的内存地址仍然是原本方法外面的对象的,所以后面用该引用的Add方法所操作的,仍然是原本方法外面的对象的内存数据
list.Add("13");
list.Add("24");
list.Add("34");
}
//2)引用本身是类似于一个“保存地址的值变量”
// 所以从方法外部传入引用到方法里,那么其实引用本身
// 是复制了一份副本来给方法里使用的,只是说这个复制
// 的引用副本和之前的引用的内容(也就是所指向的对象内存地址)
// 是一样的,所以通过引用操作对象的数据时,可以看到2个引用都操作
// 的同一个对象;但如果你是修改了引用副本本身的值内容(将该引用指向了
// 一个新的对象的内存地址),那么是不会影响到之前方法外的那个引用的,
// 所以修改后会发现2个引用所指向的对象不同了
private void ModifyList_2(List<string> list)
{
// 这里其实已经将引用指向了新的内存地址,所以后续的Add操作是在操作新对象的内存数据,而原来方法外的对象其实是没有受到影响的
list = new List<string>();
list.Add("13");
list.Add("24");
list.Add("34");
}
//3)而如果对象引用参数前加上了ref,那么方法参数所传递的不再是
// 引用的副本,而是引用的地址了(即通过引用的地址找到引用,
// 再读出引用里保存的内存地址值,再根据则个地址值去找到真正要操作的对象),
// 所以如果此时你再修改这个引用的值时,会根据引用的地址找到方法外的那个引用,
// 然后修改其内容,所以会发现方法外的引用也会指向新的对象了
private void ModifyList_ref_3(ref List<string> list)
{
// 因为有ref,所以这里其实已经将方法外原本的那个引用也指向了新的内存地址,所以后续的Add操作是在操作新对象的内存数据,并且方法外原本的那个引用也指向了这个新的对象
list = new List<string>();
list.Add("13");
list.Add("24");
list.Add("34");
}
}