未在LINQ Select后调用ToList()导致ScenarioContext中Guid值变更的原因
这个问题的核心在于LINQ的延迟执行特性,咱们一步步拆解:
1. 未调用ToList()时的本质
当你的GetMyObjects方法返回IEnumerable<MyObject>而不调用ToList()时,你返回的并不是已经生成好的对象集合——而是一个待执行的查询“蓝图”。Select里的逻辑(包括Guid.NewGuid()生成新ID的操作)并不会在调用GetMyObjects的时候立即执行,而是要等到有人枚举这个IEnumerable的时候才会触发。
2. Given步骤里发生了什么
在Given步骤中,你把_test存入ScenarioContext,但此时_test.MyObjects只是那个查询蓝图,里面的MyObject根本还没被创建,Guid.NewGuid()也没执行过。你调试时看到的Id符合预期,其实是调试器在显示内容时偷偷枚举了一次IEnumerable,触发了查询,生成了第一批Id。
3. When步骤里Id变更的原因
到了When步骤,你从ScenarioContext取出_test后,当你再次查看MyObjects(比如调试查看、或者后续业务逻辑枚举它),这个查询蓝图会再次被执行——Select里的Guid.NewGuid()会重新运行,生成全新的Id,这就是为什么你看到Id发生了变化。
4. 调用ToList()后的解决原理
ToList()方法会立即强制执行LINQ查询,把查询结果转换成一个List<MyObject>实例。这时候所有的MyObject都已经被创建,Id也通过Guid.NewGuid()生成并固定下来了。你存入ScenarioContext的是这个实实在在的List,不管后续什么时候取出、枚举它,都是用的已经生成好的对象,Id自然不会再变。
内容的提问来源于stack exchange,提问作者Mike

