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

为何含yield的IEnumerable方法异常延迟抛出?如何取消该行为?

C#中带yield的方法延迟抛出异常的原因及解决方法

问题

以下C#代码中的异常仅在枚举返回值时才抛出,这是为什么?如何让编译器取消该延迟执行行为?

public IEnumerable<string> BuildFor(Environment environment)
{
    if (environment == Environment.None)
    {
        throw new Exception($"Impossible to build for environment '{environment}'.");
    }
    string clientId = ClientIds.Api[environment];
    foreach (string scope in scopes)
    {
        yield return $"api://{clientId}/{scope}";
    }
}

原因

这是C#编译器对包含yield return的方法的特有处理:

  • 编译器会将这类方法转换为状态机实现,当你调用BuildFor时,并不会立即执行方法内部的代码,仅返回一个实现了IEnumerable<string>的状态机对象。
  • 只有当你开始枚举这个返回对象(比如通过foreach遍历、调用ToList()/ToArray()等操作)时,状态机才会启动并执行方法内的逻辑,此时参数校验的异常才会被抛出。

解决方法

要取消延迟执行,只需移除yield return,改为立即执行所有逻辑并返回已完成的集合,示例代码如下:

方式1:手动构建集合

public IEnumerable<string> BuildFor(Environment environment)
{
    if (environment == Environment.None)
    {
        throw new Exception($"Impossible to build for environment '{environment}'.");
    }
    string clientId = ClientIds.Api[environment];
    var resultList = new List<string>();
    foreach (string scope in scopes)
    {
        resultList.Add($"api://{clientId}/{scope}");
    }
    return resultList;
}

方式2:使用LINQ简化

public IEnumerable<string> BuildFor(Environment environment)
{
    if (environment == Environment.None)
    {
        throw new Exception($"Impossible to build for environment '{environment}'.");
    }
    string clientId = ClientIds.Api[environment];
    return scopes.Select(scope => $"api://{clientId}/{scope}").ToList();
}

修改后,调用BuildFor方法时会立即执行参数校验和集合构建,异常会在方法调用阶段就抛出,而非等到枚举操作时。

内容的提问来源于stack exchange,提问作者José Ramírez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:22:14