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

C#中Select语句内的方法调用为何触发多次执行?

为什么LINQ的Select会在遍历IEnumerable时多次调用转换方法?

测试代码

private static IEnumerable<Tester2> Foo()
{
    Console.WriteLine("Hello world!");
    for (var i = 0; i < 10; i++)
        yield return new Tester2(i);
}

private class Tester2
{
    public int Hey { get; set; }

    public Tester2(int hey)
    {
        Hey = hey;
    }
}

private class Tester3
{
    public int Hey3 { get; set; }

    public Tester3(int hey)
    {
        Hey3 = hey + 5;
    }
}

private static IEnumerable<Tester3> Bar(IEnumerable<Tester2> lister)
{
    Console.WriteLine("Hello world2!");
    return lister.Select(Convert);
}

private static Tester3 Convert(Tester2 tester)
{
    Console.WriteLine("Hello world3!");
    var hey = "test";
    var result= hey.Map(x => new Tester3(tester.Hey)).First();
    return result;
}

public static void Main(string[] args)
{
    
    var x = Foo().ToList();

    var bar = Bar(x);
    
    foreach (var b in bar)
    {
        Console.WriteLine("Hmm2");
    }

    
}

输出结果

Hello world!
Hello world2!
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2
Hello world3!
Hmm2

原因解析

这是因为LINQ中的Select方法是延迟执行(懒加载)的,和你熟悉的yield延迟执行逻辑一致——它不会在调用Select时就完成所有元素的转换,只是生成了一个“待执行的查询计划”。

具体代码流程拆解:

  • Foo().ToList():ToList方法会立即遍历Foo返回的所有元素,所以"Hello world!"只输出一次,10个Tester2对象被一次性创建并存入List。
  • Bar(x):调用Bar时,仅执行内部的Console.WriteLine("Hello world2!"),lister.Select(Convert)只是告诉程序“等需要元素时,用Convert方法逐个转换原集合元素”,并不会立即执行Convert。
  • 当foreach (var b in bar)遍历的时候,每循环一次需要一个Tester3元素,程序才会调用一次Convert处理对应的Tester2,因此出现"Hello world3!"和"Hmm2"交替输出10次的情况。

而添加.ToList()后(比如改成var bar = Bar(x).ToList()),ToList会立即遍历Select生成的IEnumerable,一次性完成所有10个Tester3的转换并存入List,后续遍历这个List时就不会再调用Convert了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:31:01