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

C#初学者求优化:类型检查与转换逻辑的复用实现方案

解决C#中重复类型检查与转换的复用方案

嘿,作为刚入门C#的开发者,能意识到要把重复代码封装复用,这思路真的超赞!咱们来把你ForEach里那堆类型检查+转换的逻辑好好封装一下,让代码清爽不少。

先还原下你现在可能的代码场景(应该和这个差不多对吧?):

public interface Example { /* 接口成员 */ }
public class ConcreteExample1 : Example { /* 实现 */ }
public class ConcreteExample2 : Example { /* 实现 */ }

// 你现在的循环代码
List<Example> examples = GetExamples();
examples.ForEach(example => {
    if (example is ConcreteExample1 ex1) {
        // 针对ConcreteExample1的业务逻辑
        Console.WriteLine($"处理ConcreteExample1:{ex1.Id}");
    } else if (example is ConcreteExample2 ex2) {
        // 针对ConcreteExample2的业务逻辑
        Console.WriteLine($"处理ConcreteExample2:{ex2.Name}");
    }
});

这种is检查+类型转换的逻辑如果在多个地方出现,确实很冗余,咱们用扩展方法来封装最合适,毕竟扩展方法能直接挂在Example接口上,调用起来特别直观。

方案1:通用单类型处理扩展方法

先写一个静态类来放扩展方法(记得要放在能被你的业务代码访问到的命名空间下):

public static class ExampleExtensions
{
    // 针对无返回值的处理逻辑
    public static void Handle<T>(this Example example, Action<T> handler) where T : Example
    {
        // 把类型检查和转换逻辑封装在这里
        if (example is T typedInstance)
        {
            handler(typedInstance);
        }
    }

    // 可选:如果需要有返回值的处理逻辑
    public static TResult Handle<T, TResult>(this Example example, Func<T, TResult> handler, TResult defaultValue = default) where T : Example
    {
        return example is T typedInstance ? handler(typedInstance) : defaultValue;
    }
}

现在你的循环代码可以改成这样:

examples.ForEach(example => {
    // 处理ConcreteExample1
    example.Handle<ConcreteExample1>(ex1 => {
        Console.WriteLine($"处理ConcreteExample1:{ex1.Id}");
    });
    // 处理ConcreteExample2
    example.Handle<ConcreteExample2>(ex2 => {
        Console.WriteLine($"处理ConcreteExample2:{ex2.Name}");
    });
});

这样一来,所有重复的is检查和转换都被封装到Handle方法里了,你只需要专注于业务逻辑就行。

方案2:多类型分支处理扩展方法

如果你的场景里每次都是同时处理这两个类型(不会单独处理其中一个),还可以封装一个更针对性的方法,让代码更简洁:

public static class ExampleExtensions
{
    public static void HandleExamples(this Example example, 
        Action<ConcreteExample1> handleConcrete1, 
        Action<ConcreteExample2> handleConcrete2,
        Action<Example> handleDefault = null)
    {
        switch (example)
        {
            case ConcreteExample1 ex1:
                handleConcrete1(ex1);
                break;
            case ConcreteExample2 ex2:
                handleConcrete2(ex2);
                break;
            default:
                handleDefault?.Invoke(example);
                break;
        }
    }
}

调用的时候就更清爽了:

examples.ForEach(example => example.HandleExamples(
    ex1 => Console.WriteLine($"处理ConcreteExample1:{ex1.Id}"),
    ex2 => Console.WriteLine($"处理ConcreteExample2:{ex2.Name}"),
    // 可选:默认处理逻辑
    _ => Console.WriteLine("处理未知的Example类型")
));

用switch模式匹配比if-else更清晰,以后如果新增Example的实现类,只需要在这个方法里加一个case分支就行,所有调用的地方都能直接复用。

为啥这么做更好?

  1. 减少重复代码:把类型检查+转换的逻辑只写一次,多处复用
  2. 代码更易读:业务逻辑和类型判断逻辑分离,一眼就能看到你要处理什么类型、做什么操作
  3. 维护更方便:以后如果类型结构变了,只需要修改封装的方法,不用改所有调用的地方

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:39:23