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

在IEnumerable中使用yield return时,无匹配值如何返回默认值?

问题:IEnumerable扩展方法仅在无匹配时返回默认项

我编写了如下C#扩展方法FindAllOccurrence,用于在IEnumerable<T>源中查找特定值的所有匹配项,并返回值与索引。该方法采用yield return实现,而非像List<T>.FindAll()那样返回新集合:

public static class Example
{
    public static IEnumerable<(T sought, int index)> FindAllOccurrence<T>(
        this IEnumerable<T> source, T value)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source), "The argument is null");

        if (value == null)
            throw new ArgumentNullException(nameof(value), "The argument is null");
        
        foreach (var pair in source.Select((e, i) => (e, i)))
        {
            if (pair.e.Equals(value))
            {
                yield return (pair.e, pair.i);
            }
        }

        // How do I use the if statement here?
        yield return (default(T), -1);
    }
}

当前存在的问题是,即使存在匹配项,方法末尾的yield return (default(T), -1);语句也会被执行(如下测试代码所示)。我希望仅在没有匹配值时才返回该默认值,请问如何编写合适的条件判断来避免这种情况?

测试代码:

public static void Operation()
{
    var list = new List<int>
    {
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3, 3, 3
    };

    var enumerable = list.FindAllOccurrence(3);

    foreach (var (value, index) in enumerable)
    {
        Console.WriteLine($"value: {value}, index: {index}");
    }
}

解决方案

核心思路是添加一个布尔标记,记录遍历过程中是否找到过匹配项。遍历结束后,仅当标记为false时才返回默认项。修改后的代码如下:

public static class Example
{
    public static IEnumerable<(T sought, int index)> FindAllOccurrence<T>(
        this IEnumerable<T> source, T value)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source), "The argument is null");

        if (value == null)
            throw new ArgumentNullException(nameof(value), "The argument is null");
        
        bool found = false; // 标记是否找到匹配项
        foreach (var pair in source.Select((e, i) => (e, i)))
        {
            if (pair.e.Equals(value))
            {
                found = true;
                yield return (pair.e, pair.i);
            }
        }

        // 仅当无匹配时返回默认项
        if (!found)
        {
            yield return (default(T), -1);
        }
    }
}

关键说明:

  • 新增bool found = false;变量,初始状态为未找到匹配。
  • 每次找到匹配项并yield return时,将found设为true。
  • 遍历完成后,通过if (!found)判断,仅在无任何匹配时才返回(default(T), -1)。

测试效果:

  • 当原测试代码运行时,只会输出所有匹配的项(索引2、10、11、12对应的3),不会再出现末尾的默认项。
  • 如果传入的列表中没有目标值,比如var list = new List<int>{1,2,4};,则会输出value: 0, index: -1(int的default值为0)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:55:19