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

如何告知有返回值的调用方法:ThrowException调用后执行会终止?

问题解决:调用ThrowException后编译器要求返回值的处理

问题根源

你的代码里有两个核心问题导致编译器报错:

  1. 非UI线程调用ThrowException时用了BeginInvoke异步执行,当前线程不会立即终止,编译器会认为方法需要继续执行并返回值;
  2. 编译器无法自动推断ThrowException方法一定会抛出异常,即使UI线程分支是直接throw,仍会要求调用方法返回值。

解决方案

方案1:用[DoesNotReturn]标记方法(推荐C#7.0+)

给ThrowException加上[DoesNotReturn]属性,告诉编译器这个方法永远不会正常返回,同时把BeginInvoke改成Invoke同步执行,确保当前线程会终止:

using System.Diagnostics.CodeAnalysis;

internal static class ExceptionHelper
{
    [DoesNotReturn]
    internal static void ThrowException(Exception e)
    {
        var dispatcher = App.Current.Dispatcher;

        if (dispatcher != null)
        {
            if (!dispatcher.CheckAccess())
            {
                // 改用Invoke同步调用,确保当前线程等待UI线程抛出异常后终止
                dispatcher.Invoke((ThreadStart)delegate
                {
                    throw e;
                }, DispatcherPriority.Normal);
            }
            else
            {
                throw e;
            }
        }
        // 兜底逻辑:dispatcher为空时直接抛出,保证方法无正常返回
        throw e;
    }
}

调用时无需返回值,编译器不再报错:

private SomeEnum DoSomeException()
{
    var e = new NotImplementedException();
    ExceptionHelper.ThrowException(e);
    // 此处不需要return,编译器会识别方法已终止
}

方案2:泛型返回方法(兼容低版本C#)

如果项目用的是C#7.0以下版本,可以封装泛型方法,返回一个永远不会被执行到的默认值,满足编译器要求:

internal static class ExceptionHelper
{
    internal static T ThrowException<T>(Exception e)
    {
        var dispatcher = App.Current.Dispatcher;

        if (dispatcher != null)
        {
            if (!dispatcher.CheckAccess())
            {
                dispatcher.Invoke(() => throw e, DispatcherPriority.Normal);
            }
            else
            {
                throw e;
            }
        }
        throw e;
        // 仅为满足编译器语法要求,永远不会执行到
        return default(T);
    }
}

调用时直接返回该方法的结果:

private SomeEnum DoSomeException()
{
    var e = new NotImplementedException();
    return ExceptionHelper.ThrowException<SomeEnum>(e);
}

重要提醒

  • 绝对不能用BeginInvoke:异步调用会让当前线程继续执行,不仅编译器报错,还会导致方法后续逻辑(如果有)意外执行,彻底违背“抛出异常即终止”的初衷;
  • [DoesNotReturn]需要引用System.Diagnostics.CodeAnalysis命名空间,若项目版本过低,需在项目文件中设置<LangVersion>7.0</LangVersion>或更高版本。

内容的提问来源于stack exchange,提问作者T. Hench

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:35:25