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

针对类型转换式分支逻辑,有无更佳替代方案?能否用switch-case实现?

替代类型判断分支的方案及switch-case实现

首先,完全可以用switch-case实现该逻辑,C# 7.0及以上支持类型模式匹配的switch语句,能替代原有的if-else分支,代码更简洁易读:

public class Test{
    public Animal DoSomething(AnimalCreateDto animal){
        return animal switch
        {
            DogCreateDto dogDto => Create(new Dog(dogDto)),
            CatCreateDto catDto => Create(new Cat(catDto)),
            _ => throw new ArgumentException("不支持的AnimalCreateDto类型")
        };
    }

    private Dog Create(Dog dog){ ... }
    private Cat Create(Cat cat){ ... }
}

(注:原代码里的CateCreateDto应为笔误,修正为CatCreateDto)

除了switch-case,还有几种更优的方案可以彻底消除类型判断分支:

1. 多态模式(推荐,符合开闭原则)

让AnimalCreateDto定义抽象方法,子类负责将自身转换为对应的Animal实体,这样DoSomething无需任何类型判断:

// 定义抽象基类
public abstract class AnimalCreateDto
{
    public abstract Animal ToAnimal();
}

public class DogCreateDto : AnimalCreateDto
{
    public override Animal ToAnimal() => new Dog(this);
}

public class CatCreateDto : AnimalCreateDto
{
    public override Animal ToAnimal() => new Cat(this);
}

// Test类简化为:
public class Test{
    public Animal DoSomething(AnimalCreateDto animal){
        var animalEntity = animal.ToAnimal();
        return Create(animalEntity);
    }

    // 可统一为一个Create方法(逻辑允许的话),或保留重载
    private Animal Create(Animal animal){ 
        // 根据实际类型处理,若Create逻辑也能抽象到Animal子类,可彻底消除判断
        if(animal is Dog dog) { ... }
        else if(animal is Cat cat) { ... }
    }
}

如果Create的逻辑也能通过Animal子类的多态方法实现(比如animal.Save()),那连最后的类型判断也能消除,完全遵循开闭原则——新增动物类型时,只需新增Dto和Animal子类,无需修改Test类代码。

2. 类型映射字典

如果无法修改Dto结构,可用字典存储类型到处理逻辑的映射,避免硬编码分支:

public class Test{
    private static readonly Dictionary<Type, Func<AnimalCreateDto, Animal>> _typeHandlers = new()
    {
        { typeof(DogCreateDto), dto => Create(new Dog((DogCreateDto)dto)) },
        { typeof(CatCreateDto), dto => Create(new Cat((CatCreateDto)dto)) }
    };

    public Animal DoSomething(AnimalCreateDto animal){
        if(_typeHandlers.TryGetValue(animal.GetType(), out var handler))
        {
            return handler(animal);
        }
        throw new ArgumentException("不支持的AnimalCreateDto类型");
    }

    private Dog Create(Dog dog){ ... }
    private Cat Create(Cat cat){ ... }
}

新增类型时,只需在字典中添加对应条目,无需修改DoSomething方法逻辑。

3. 访问者模式(适合复杂场景)

如果Dto结构复杂且无法修改,同时需要对不同类型Dto执行多种操作,访问者模式是合适的选择:

// 定义访问者接口
public interface IAnimalCreateDtoVisitor<T>
{
    T Visit(DogCreateDto dto);
    T Visit(CatCreateDto dto);
}

// 让Dto接受访问者
public abstract class AnimalCreateDto
{
    public abstract T Accept<T>(IAnimalCreateDtoVisitor<T> visitor);
}

public class DogCreateDto : AnimalCreateDto
{
    public override T Accept<T>(IAnimalCreateDtoVisitor<T> visitor) => visitor.Visit(this);
}

public class CatCreateDto : AnimalCreateDto
{
    public override T Accept<T>(IAnimalCreateDtoVisitor<T> visitor) => visitor.Visit(this);
}

// 实现创建Animal的访问者
public class AnimalCreationVisitor : IAnimalCreateDtoVisitor<Animal>
{
    private readonly Test _test;

    public AnimalCreationVisitor(Test test) => _test = test;

    public Animal Visit(DogCreateDto dto) => _test.Create(new Dog(dto));
    public Animal Visit(CatCreateDto dto) => _test.Create(new Cat(dto));
}

// Test类使用访问者
public class Test{
    public Animal DoSomething(AnimalCreateDto animal){
        var visitor = new AnimalCreationVisitor(this);
        return animal.Accept(visitor);
    }

    private Dog Create(Dog dog){ ... }
    private Cat Create(Cat cat){ ... }
}

这种方式适合需要对Dto执行多种不同操作的场景,新增类型时只需扩展访问者接口和实现类,以及Dto的Accept方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:15:36