Unity C#底层原理(一)

析构函数

当引用类型的堆内存被回收时
析构函数是当垃圾真正被回收的时候才会调用的函数

class AA
{
	~AA()
	{
		
	}
}

垃圾回收

GC只负责堆(heap)内存的垃圾回收(需要CPU计算,降低性能,卡顿)
引用类型都是存在堆(heap)中的,所以它的分配和释放都需要通过垃圾回收机制管理

栈(stack)上的内存是由系统自动管理的
值类型在栈(stack)中分配内存,有自己的生命周期,会自动分配和释放

C# 回收机制的大概原理
0代内存 1代内存 2代内存
1、在第一次垃圾回收开始时,会从堆标记对象,从根(静态字段、方法参数)开始检查引用对象,标记可达对象和不可达对象,不可达对象就是垃圾。2、搬迁对象压缩堆
当0代进行垃圾回收的时候,会将可达对象放入1代内存。
当1代满了的时候,会带着0代一起进行垃圾回收,然后把可达对象移动到2代内存中
2代满了,会带着1代0代一起进行垃圾回收

索引器

 public class Test
    {
        private Indexer _indexer = new Indexer();
        public Test()
        {
            _indexer[0] = 10;
            Debug.LogError(_indexer[0]);
        }
    }

    public class Indexer
    {
        private List<int> values = new List<int>() {1, 2, 3};
        public int this[int index]
        {
            get { return values[index];}
            set { values[index] = value; }
        }
    }

拓展方法

 public class Test
    {
        public Test()
        {
            int A = 10;
            A.ChangeValue();//11
        }
    }
    //一定在静态类中,必须是静态函数
    public static class Teststatic
    {
        public static void ChangeValue(this int value)
        {
            Debug.LogError(value+1);
        }
    }

运算符重载

public class Test
    {
        public Test()
        {
            Tests2 T2 = new Tests2();
            T2.value = 10;
            T2 += 20;
        }
    }
    
    public class Tests2
    {
        public int value;
        //必须是公共静态方法
        //参数至少有一个是 Tests2 返回值随意
        public static Tests2 operator +(Tests2 A,int B)
        {
            A.value+=B;
            return A;
        }
    }

密封类

在这里插入图片描述
——————————————————————————————————

数组

数组(Array):大小固定,存储单元是连续的内存地址。一旦创建,大小不可更改。适用于需要快速访问元素的情况。

动态数组

ArrayList:非泛型集合,底层是 object[],在容量不足时会创建更大的数组并复制元素。缺乏类型安全,存储值类型时需要装箱和拆箱。
List:泛型集合,底层是 T[],避免了装箱和拆箱,提供类型安全。在容量不足时,同样会创建更大的数组并复制元素。

栈和队列

Stack:非泛型集合,先进后出(LIFO),底层是 object[]。扩展容量规则与 ArrayList 一样。
Queue:非泛型集合,先进先出(FIFO),底层是 object[]。扩展容量规则与 ArrayList 一样。
Stack 和 Queue:泛型版本,提供类型安全,底层是 T[]。

上面的底层都是数组[],是一串连续地址的存储单元构成的集合,顺序存储
散列表

Hashtable:非泛型键值对集合,使用哈希表实现,适用于快速查找。键和值都是 object 类型。
Dictionary<TKey, TValue>:泛型键值对集合,使用哈希表实现,提供类型安全,避免装箱和拆箱。

下面是由任意地址的存储单元构成的集合,链式存储
链表

LinkedList:双向链表,链式存储,适用于频繁插入和删除操作。
单向链表:只有单向指针的链表,C#标准库没有提供内置的单向链表实现。
循环链表:链表的最后一个节点指向第一个节点,C#标准库没有提供内置的循环链表实现。

——————————————————————————————————

不重要

其他集合类
SortedList:键值对集合,按键排序,底层是 ArrayList 和 Hashtable 的组合。
SortedList<TKey, TValue>:泛型键值对集合,按键排序,底层是 List 和 Dictionary<TKey, TValue> 的组合。
SortedDictionary<TKey, TValue>:泛型键值对集合,按键排序,底层是红黑树。
SortedSet:泛型集合,元素按顺序排序,底层是红黑树。
HashSet:泛型集合,元素无序且唯一,使用哈希表实现。
ConcurrentDictionary<TKey, TValue>:线程安全的键值对集合,适用于并发操作。
其他补充
BitArray:存储位(布尔值)的数组,提供按位操作。
Queue:先进先出(FIFO)的泛型集合,适用于队列操作。
Stack:先进后出(LIFO)的泛型集合,适用于栈操作。
ObservableCollection:实现了 INotifyCollectionChanged 接口的集合,用于数据绑定。
ReadOnlyCollection:包装一个现有集合,使其只读。

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity协程的底层实现是基于C#的迭代器实现的。在C#中,使用yield关键字可以将方法转换为迭代器,通过迭代器可以实现协程的效果。Unity中的协程也是基于这个原理实现的。 如果要自己实现一个协程,可以按照以下步骤进行: 1. 定义一个委托,用于表示协程的执行体。 ```csharp public delegate IEnumerator CoroutineDelegate(); ``` 2. 定义一个协程类,保存协程的执行体和当前执行状态。 ```csharp public class Coroutine { private CoroutineDelegate m_CoroutineDelegate; private IEnumerator m_Enumerator; private bool m_IsDone; public bool IsDone { get { return m_IsDone; } } public Coroutine(CoroutineDelegate coroutineDelegate) { m_CoroutineDelegate = coroutineDelegate; m_Enumerator = m_CoroutineDelegate(); m_IsDone = false; } public void Update() { if (m_Enumerator != null && !m_IsDone) { if (!m_Enumerator.MoveNext()) { m_IsDone = true; } } } } ``` 3. 在需要使用协程的地方,创建一个协程对象并添加到一个协程管理器中。 ```csharp public class CoroutineManager : MonoBehaviour { private static CoroutineManager m_Instance; private List<Coroutine> m_Coroutines = new List<Coroutine>(); public static CoroutineManager Instance { get { if (m_Instance == null) { m_Instance = new GameObject("CoroutineManager").AddComponent<CoroutineManager>(); } return m_Instance; } } private void Update() { for (int i = m_Coroutines.Count - 1; i >= 0; i--) { Coroutine coroutine = m_Coroutines[i]; coroutine.Update(); if (coroutine.IsDone) { m_Coroutines.RemoveAt(i); } } } public Coroutine StartCoroutine(CoroutineDelegate coroutineDelegate) { Coroutine coroutine = new Coroutine(coroutineDelegate); m_Coroutines.Add(coroutine); return coroutine; } } ``` 4. 在协程中使用yield关键字来实现挂起和恢复。 ```csharp private IEnumerator MyCoroutine() { Debug.Log("Start Coroutine"); yield return null; Debug.Log("Wait One Frame"); yield return new WaitForSeconds(1.0f); Debug.Log("Wait One Second"); yield return new WaitForEndOfFrame(); Debug.Log("Wait End Of Frame"); } ``` 以上就是一个简单的协程实现。注意,实际应用中还需要考虑协程的取消、异常处理等问题,需要根据具体需求进行扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值