问:什么是装箱?
剑之初: 装箱转换是指将一个值类型隐式地转换成一个object 类型,或者把这个值类型转换成一个被该值类型应用的接口类型interface-type。把一个值类型的值装箱,也就是创建一个object 实例并将这个值复制给这个object。比如:
int i = 10;
object obj = i;
用下图所示,可以表示装箱的过程
我们也可以用显式的方法来进行装箱操作:
int i = 10;
object obj =(object)i;
-------------------------------------------------------------------------------------------------------------------------
问:什么是拆箱?
剑之初:和装箱转换正好相反,拆箱转换是指将一个对象类型显式地转换成一个值类型,或是将一个接口类型显式地转换成一个执行该接口的值类型。
拆箱的过程分为两步:首先,检查这个对象实例,看它是否为给定的值类型的装箱值。然后,把这个实例的值拷贝给值类型的变量。
利用如下例子:
int i = 10;
object obj = i;
int j = (int)obj;
拆箱的过程用图来表示就是:
可以看出拆箱过程正好是装箱过程的逆过程。必须注意,装箱转换和拆箱转换必须遵循类型兼容原则。
那么接下来进入正题,我们将如何避免这样的装箱与拆箱操作呢?
剑之初采用的方式是创建自己的数据类型库,在内部根据泛型进行转换.具体骚操作如下:
创建数据类型库的基类: VartableBase.cs
话不多说上代码!!!:
#region 模块信息
//===================================================
// Copyright (C) 2020
//
// 文件名(File Name): VartableBase.cs
// 作者(Author): 稀饭
// 邮箱(e-mail): 1144000915@qq.com
// 创建时间(CreateTime): 2021-01-11 15:20:13
// 修改者列表(modifier):
// 模块描述(Module description): 创建脚本自动修改文件名、作者、创建时间
//===================================================
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YouYou
{
/// <summary>
/// 变量基类
/// </summary>
public abstract class VartableBase {
/// <summary>
/// 获取变量类型
/// </summary>
public abstract Type Type
{
get;
}
/// <summary>
/// 引用计数
/// </summary>
public byte ReferenceCount
{
get;
private set;
}
/// <summary>
/// 变量引用计数增加
/// </summary>
public void Retain()
{
ReferenceCount++;
}
/// <summary>
/// 变量引用计数减少 变量回池
/// </summary>
public void Release()
{
ReferenceCount--;
if (ReferenceCount<1)
{
//回池操作
GameEntry.Pool.EnqueueVarObject(this);
}
}
}
}
定义变量泛型基类:
#region 模块信息
//===================================================
// Copyright (C) 2020
//
// 文件名(File Name): Vartable.cs
// 作者(Author): 稀饭
// 邮箱(e-mail): 1144000915@qq.com
// 创建时间(CreateTime): 2021-01-11 15:20:05
// 修改者列表(modifier):
// 模块描述(Module description): 创建脚本自动修改文件名、作者、创建时间
//===================================================
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YouYou
{
/// <summary>
/// 变量泛型基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class Vartable<T> : VartableBase
{
/// <summary>
/// 当前存储的真实值
/// </summary>
public T Value;
/// <summary>
/// 变量类型
/// </summary>
public override Type Type
{
get
{
return typeof(T);
}
}
}
}
例如我们现在需要一个byte类型,那么就创建一个脚本:VarByte.cs
#region 模块信息
//===================================================
// Copyright (C) 2020
//
// 文件名(File Name): VarByte.cs
// 作者(Author): 稀饭
// 邮箱(e-mail): 1144000915@qq.com
// 创建时间(CreateTime): 2021-01-12 16:32:47
// 修改者列表(modifier):
// 模块描述(Module description): 创建脚本自动修改文件名、作者、创建时间
//===================================================
#endregion
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YouYou
{
public class VarByte : Vartable<byte> {
/// <summary>
/// 分配一个对象
/// </summary>
/// <returns></returns>
public static VarByte Alloc()
{
VarByte var = GameEntry.Pool.DequeueVarObject<VarByte>();
var.Value = 0;
var.Retain();
return var;
}
/// <summary>
/// 分配一个对象
/// </summary>
/// <param name="value">初始值</param>
/// <returns></returns>
public static VarByte Alloc(byte value)
{
VarByte var = Alloc();
var.Value = value;
return var;
}
/// <summary>
/// VarByte -> byte
/// </summary>
/// <param name="value"></param>
public static implicit operator byte(VarByte value)
{
return value.Value;
}
}
}
准备工作全部准备好了我们开始使用他们!
备注提醒: 下面的测试脚本有调用我写的变量对象池脚本与状态机脚本,本篇论文只是为了传输思想,代码不可直接拿来使用!
添加数据到数据字典中:
/// <summary>
/// 设置参数值
/// </summary>
/// <typeparam name="TData">泛型类型</typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
public void SetData<TData>(string key,TData value)
{
VartableBase itemBase = null;
if (m_ParamDic.TryGetValue(key,out itemBase))
{
Vartable<TData> item = itemBase as Vartable<TData>;
item.Value = value;
m_ParamDic[key] = item;
}else
{
//参数原来不存在
Vartable<TData> item = new Vartable<TData>();
item.Value = value;
m_ParamDic[key] = item;
}
}
获取数据
/// <summary>
/// 获取数据
/// </summary>
/// <typeparam name="TData">泛型类型</typeparam>
/// <param name="key"></param>
/// <returns></returns>
public TData GetData<TData>(string key)
{
VartableBase itemBase = null;
if (m_ParamDic.TryGetValue(key, out itemBase))
{
Vartable<TData> item = itemBase as Vartable<TData>;
return item.Value;
}
return default(TData);
}
设置与获取写好了,来最后看下调用时的样子:
调用设置属性
GameEntry.Prosedure.SetData("code", Random.Range(1, 100));
GameEntry.Prosedure.SetData("name", "稀饭开发");
调用获取属性 注意!!!在获取并没有进行装箱与拆箱的操作!!!
string name = GameEntry.Prosedure.GetData<string>("name");
int code = GameEntry.Prosedure.GetData<int>("code");
Debug.Log("name= " + name);
Debug.Log("code= " + code);
这时候有人问了.虽然没有进行装箱与拆箱操作,你频繁的创转VarByte的对象就不消耗性能了么?
剑之初: 创建一个数据变量池就好了! GetType获取类型当key.存到池中!!! 即可!!!