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

C#中如何仅通过异常名称字符串实例化并抛出对应异常

C#通过字符串异常名称实例化并抛出异常的实现方案

直接通过字符串类名执行new操作是不被C#语法支持的,你可以根据项目场景选择以下两种可行方案:


方案1:反射动态加载类型(适合异常种类动态扩展的场景)

核心逻辑是通过反射根据字符串类名查找对应的异常类型,再调用构造函数创建实例后抛出,实现步骤如下:

  • 先确定所有自定义异常所在的命名空间、所属程序集,拼接出类型的完整名称
  • 校验加载到的类型是否为Exception的子类,避免加载无效类型
  • 匹配异常类的构造函数(优先支持传入自定义错误消息的构造,回退到无参构造)
  • 创建实例后直接抛出

完整实现代码:

using System;
using System.Reflection;

public static class ExceptionThrower
{
    // 替换为你项目中异常类所在的命名空间
    private const string ExceptionNamespace = "YourProject.Exceptions";
    // 替换为异常类所在的程序集,示例中取当前类所在程序集
    private static readonly Assembly ExceptionAssembly = typeof(ExceptionThrower).Assembly;

    public static void Throw(string exceptionName, string message = null)
    {
        // 拼接类型全名称
        string fullType = $"{ExceptionNamespace}.{exceptionName}";
        Type exType = ExceptionAssembly.GetType(fullType);

        // 校验类型有效性
        if (exType == null || !typeof(Exception).IsAssignableFrom(exType))
        {
            throw new ArgumentOutOfRangeException(nameof(exceptionName), $"无效的异常名称:{exceptionName}");
        }

        Exception exInstance;
        // 优先使用带string消息参数的构造函数
        if (!string.IsNullOrEmpty(message))
        {
            ConstructorInfo msgCtor = exType.GetConstructor(new[] { typeof(string) });
            if (msgCtor != null)
            {
                exInstance = (Exception)msgCtor.Invoke(new object[] { message });
                throw exInstance;
            }
        }
        // 无消息时使用无参构造
        exInstance = (Exception)Activator.CreateInstance(exType);
        throw exInstance;
    }
}

调用示例:

string myException = "ConflictException";
ExceptionThrower.Throw(myException, "当前资源状态冲突,操作失败");

方案2:预定义工厂映射字典(适合异常种类固定的场景)

如果你的异常集合是固定的,优先用字典做名称到异常工厂的映射,相比反射性能更高、类型更安全,不会出现命名空间不匹配、构造函数缺失的运行时问题:

using System;
using System.Collections.Generic;

public static class ExceptionThrower
{
    private static readonly Dictionary<string, Func<string, Exception>> _exFactories = new()
    {
        ["ConflictException"] = msg => new ConflictException(msg),
        ["InternalServerErrorException"] = msg => new InternalServerErrorException(msg),
        // 新增异常时只需在这里添加对应映射即可
    };

    public static void Throw(string exceptionName, string message = null)
    {
        if (!_exFactories.TryGetValue(exceptionName, out var factory))
        {
            throw new ArgumentOutOfRangeException(nameof(exceptionName), $"无效的异常名称:{exceptionName}");
        }
        throw factory(message ?? "服务发生未知错误");
    }
}

注意事项

  • 如果你的异常分布在多个不同程序集,反射方案中需要遍历当前应用域已加载的所有程序集查找目标类型,不要仅限定单个程序集
  • 无论使用哪种方案,都必须校验最终生成的对象是Exception的子类,否则抛出时会触发运行时错误
  • 如果你的自定义异常需要额外构造参数(如错误码、内部异常对象),可以对应调整构造函数传参逻辑或工厂方法的入参

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:12:42