我遇到了一个奇怪的问题,我想知道我应该做什么.
我有这个类返回一个IEnumerable< MyClass>这是延期执行.现在有两个可能的消费者.其中一个排序结果.
请参见以下示例:
public class SomeClass { public IEnumerable<MyClass> GetMyStuff(Param givenParam) { double culmulativeSum = 0; return myStuff.Where(...) .OrderBy(...) .TakeWhile( o => { bool returnValue = culmulativeSum < givenParam.Maximum; culmulativeSum += o.someNumericValue; return returnValue; }; } }
消费者称延迟执行只有一次,但是如果它们被称为更多的结果,结果将是错误的,因为culmulativeSum不会被重置.我通过无意识的单元测试发现了这个问题.
解决这个问题的最简单的方法是添加.ToArray(),并以一点点开销为代价去除延迟执行.
我也可以在消费者阶层添加单元测试,以确保他们只将它们称为一次,但这并不会阻止任何新的消费者在未来从这个潜在的问题编码.
我想到的另一件事是让后续执行.
就像是
return myStuff.Where(...) .OrderBy(...) .TakeWhile(...) .ThrowIfExecutedMoreThan(1);
显然这不存在.
实施这样的事情会是个好主意,你会怎么做?
否则,如果有一个大的粉红色的大象,我看不到,指出它将不胜感激. (我觉得有一个,因为这个问题是一个非常基本的情况:|)
编辑:
这是一个不好的消费者使用示例:
public class ConsumerClass { public void WhatEverMethod() { SomeClass some = new SomeClass(); var stuffs = some.GetMyStuff(param); var nb = stuffs.Count(); //first deferred execution var firstOne = stuff.First(); //second deferred execution with the culmulativeSum not reset } }
解决方法
您可以通过简单地将您的方法转换为
iterator来解决不正确的结果问题:
double culmulativeSum = 0; var query = myStuff.Where(...) .OrderBy(...) .TakeWhile(...); foreach (var item in query) yield return item;
它可以以简单的扩展方法封装:
public static class Iterators { public static IEnumerable<T> Lazy<T>(Func<IEnumerable<T>> source) { foreach (var item in source()) yield return item; } }
那么在这种情况下你需要做的就是用Iterators.Lazy调用包围原始方法体.例如:
return Iterators.Lazy(() => { double culmulativeSum = 0; return myStuff.Where(...) .OrderBy(...) .TakeWhile(...); });
原文地址:https://www.jb51.cc/csharp/94643.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。