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

C#如何从含父类与子类的列表中高效创建子类对象?

优化子类实例复制方案,告别低效的类型判断

先明确场景:你有父类AnimalGroup,以及继承它的子类LionGroup、GiraffeGroup,Wild列表中存储了这些子类的实例,现在需要基于Wild生成新的Zoo列表,每个元素是原对象的副本。原实现通过逐个判断类型创建实例,不仅代码冗余,后续新增子类还要修改判断逻辑,效率和维护性都很差。下面是几种更优的实现方式:

方案1:用多态让子类自行负责复制(最推荐)

给父类定义抽象的Clone方法,每个子类自己实现复制逻辑,彻底消除类型判断:

public abstract class AnimalGroup
{
    public string Name { get; set; }
    // 抽象复制方法,子类必须实现自身的复制逻辑
    public abstract AnimalGroup Clone();
}

public class LionGroup : AnimalGroup
{
    public int PrideSize { get; set; }

    public override AnimalGroup Clone()
    {
        // 此处为浅复制,若包含引用类型成员,可自行扩展为深复制
        return new LionGroup
        {
            Name = this.Name,
            PrideSize = this.PrideSize
        };
    }
}

public class GiraffeGroup : AnimalGroup
{
    public int NeckAverageLength { get; set; }

    public override AnimalGroup Clone()
    {
        return new GiraffeGroup
        {
            Name = this.Name,
            NeckAverageLength = this.NeckAverageLength
        };
    }
}

// 生成Zoo列表只需一行代码
List<AnimalGroup> Zoo = Wild.Select(animal => animal.Clone()).ToList();

这个方案的优势:

  • 完全无需类型判断,代码简洁高效
  • 新增子类时只需实现Clone方法,原有代码无需修改,符合开闭原则
  • 每个子类自主控制复制逻辑,可灵活实现浅复制或深复制

方案2:用反射动态复制(适合无法修改原有类的场景)

如果不能改动父类和子类的结构,可通过反射根据对象类型动态创建实例并复制属性:

using System.Reflection;

public static class AnimalCopier
{
    public static T Clone<T>(T source) where T : AnimalGroup, new()
    {
        var target = new T();
        // 复制所有公共实例属性
        var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var prop in props)
        {
            if (prop.CanRead && prop.CanWrite)
            {
                prop.SetValue(target, prop.GetValue(source));
            }
        }
        return target;
    }
}

// 生成Zoo列表
List<AnimalGroup> Zoo = Wild.Select(animal => 
{
    var cloneMethod = typeof(AnimalCopier).GetMethod("Clone").MakeGenericMethod(animal.GetType());
    return (AnimalGroup)cloneMethod.Invoke(null, new object[] { animal });
}).ToList();

注意:反射性能略逊于多态,但比重复类型判断更易维护。若频繁调用,可缓存反射获取的方法以提升性能。

方案3:用类型映射字典替代重复判断

提前将类型与对应的复制逻辑存入字典,避免每次的类型判断开销:

// 提前注册各类型的复制委托
private static readonly Dictionary<Type, Func<AnimalGroup, AnimalGroup>> _cloneHandlers = new()
{
    { typeof(LionGroup), g => new LionGroup { Name = g.Name, PrideSize = ((LionGroup)g).PrideSize } },
    { typeof(GiraffeGroup), g => new GiraffeGroup { Name = g.Name, NeckAverageLength = ((GiraffeGroup)g).NeckAverageLength } }
};

// 生成Zoo列表
List<AnimalGroup> Zoo = Wild.Select(g => _cloneHandlers[g.GetType()](g)).ToList();

这种方式比if-else或switch判断更高效,新增子类时只需在字典中添加一行委托即可,代码结构更清晰。

内容的提问来源于stack exchange,提问作者Alibies

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:17:41