Unity C#自定义可序列化字典泛型Add方法如何实现引用类型值传递
Unity C# 泛型序列化字典引用类型值拷贝解决方案
核心问题说明
C#泛型语法原生不支持带参数的构造函数约束,因此无法直接通过new T(Value)的方式在泛型方法内创建拷贝实例,以下是三种可直接落地的实现方案:
方案1:自定义深拷贝接口(性能最优)
首先定义统一的深拷贝接口,所有需要按值存储的引用类型都实现该接口:
public interface IDeepCopyable<T> { /// <summary> /// 返回当前对象的深拷贝实例 /// </summary> T DeepCopy(); }
修改你的Add方法,增加类型判断和拷贝逻辑:
public bool Add(in S Key, in T Value) { // 键重复校验 for (int i = 0; i < KeyValuePairs.Count; i++) { if (KeyValuePairs[i].Key.Equals(Key)) { Debug.LogError($"Key '{Key}' already exists in the AMADictionary."); return false; } } T storedValue = Value; // 仅对实现了深拷贝接口的引用类型执行拷贝 if (!typeof(T).IsValueType && storedValue is IDeepCopyable<T> copyableInstance) { storedValue = copyableInstance.DeepCopy(); } KeyValuePairs.Add(new AMAKeyValuePair<S, T>(Key, storedValue)); return true; }
针对系统自带的引用类型(如List<T>),可以封装可拷贝的子类适配需求:
[Serializable] // 适配Unity序列化要求 public class DeepCopyableList<T> : List<T>, IDeepCopyable<DeepCopyableList<T>> { public DeepCopyableList() {} public DeepCopyableList(IEnumerable<T> collection) : base(collection) {} public DeepCopyableList<T> DeepCopy() { // 如果T也是引用类型,可在此处扩展递归拷贝逻辑 return new DeepCopyableList<T>(this); } }
方案2:序列化反序列化通用拷贝(无需修改类型定义)
利用Unity自带的JsonUtility做通用深拷贝,适合所有已经标记了[Serializable]的类型,完美适配ScriptableObject的使用场景:
private T DeepCopyByJson(T source) { // 值类型和空引用直接返回 if (typeof(T).IsValueType || source == null) return source; string jsonData = JsonUtility.ToJson(source); return JsonUtility.FromJson<T>(jsonData); }
直接在Add方法中调用该方法即可:
T storedValue = DeepCopyByJson(Value);
方案3:委托注入拷贝逻辑(灵活性最高)
如果同一种类型在不同场景下需要不同的拷贝规则,可以给字典类添加可选的拷贝委托:
public class AMADictionary<S, T> { // 自定义拷贝逻辑委托,为空则直接使用原实例 public Func<T, T> CopyHandler = null; // 其余原有逻辑省略 public bool Add(in S Key, in T Value) { // 键重复校验逻辑省略 T storedValue = CopyHandler == null ? Value : CopyHandler(Value); KeyValuePairs.Add(new AMAKeyValuePair<S, T>(Key, storedValue)); return true; } }
使用时按需配置拷贝逻辑即可,比如针对List<int>类型的字典:
var intListDict = new AMADictionary<string, List<int>>(); intListDict.CopyHandler = (sourceList) => new List<int>(sourceList);
方案选择建议:
- 优先选方案1,无额外性能开销,可控性最高
- 临时适配现有可序列化类型选方案2,无需修改原有类型定义
- 同类型多场景拷贝规则不同时选方案3
内容的提问来源于stack exchange,提问作者Abdul Moiz Haroon
相关产品推荐
相关产品推荐

