You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 19:00:01