在C#/Linq中方便地使用部分/流式枚举
有时,在处理数组中的元素时,我发现将IEnumerable视为指定类型的只读流是很有价值的。在诸如字节和文本操作之类的实例中,.Net的StreamReader和TextReader类在某种程度上涵盖了这一点,但它们的接口并不像Linq这样干净 我对IEnumerable的最初(也是有缺陷的)理解是,它以某种方式跟踪它在iterable中的位置,而不是在每次使用时开始新的迭代 我在处理包含[4字节][n字节]序列的IEnumerable时尝试使用它,其中'n'是前4个字节指定的长度,类似于:在C#/Linq中方便地使用部分/流式枚举,c#,linq,parsing,stream,C#,Linq,Parsing,Stream,有时,在处理数组中的元素时,我发现将IEnumerable视为指定类型的只读流是很有价值的。在诸如字节和文本操作之类的实例中,.Net的StreamReader和TextReader类在某种程度上涵盖了这一点,但它们的接口并不像Linq这样干净 我对IEnumerable的最初(也是有缺陷的)理解是,它以某种方式跟踪它在iterable中的位置,而不是在每次使用时开始新的迭代 我在处理包含[4字节][n字节]序列的IEnumerable时尝试使用它,其中'n'是前4个字节指定的长度,类似于: v
var len = BitConverter.ToInt32(input.Take(4), 0);
return input.Take(len);
这是不正确的,因为“input”可枚举项没有被Take调用修改(正如它的设计所期望的那样),前4个字节被双重表示,4个未读。可以使用对“Skip”的调用,但会调用源的多个枚举,这是不需要的。ToArray()调用是该问题的修补解决方案,但在处理大数据块时,可能会通过多个存储消耗过多的内存。我正在寻找一种执行此行为的替代方法,其中可枚举项以类似于流的行为向前移动
这种行为可以部分地用枚举数上的扩展方法来模拟,但它依赖于用户管理,或者可能依赖于实现的多次处理,这似乎有些笨拙。例如:
public static IEnumerable<T> Take<T>(this IEnumerator<T> enumerator, int count) {
for(int i = 0; i < count; ++i) {
if(!enumerator.MoveNext()) {
using(enumerator) {
break;
}
}
yield return enumerator.Current;
}
}
public static IEnumerable<T> AsEnumerable<T>(this IEnumerator<T> enumerator) {
using(enumerator) {
while(enumerator.MoveNext()) {
yield return enumerator.Current;
}
}
}
公共静态IEnumerable Take(此IEnumerator枚举器,int count){
对于(int i=0;i
总而言之,虽然我的问题暗示解决方案可能在于枚举机制,但我正在寻找一种对任意类型的流进行操作的干净方法,该流还可以(干净地)处理维度依赖于或由以前的元素声明的格式。因为这是解析中的一项常见任务(通常不使用原始字节流或文本流,如请求泛型支持),例如,我认为有一种相对简洁的方法来处理它?可以通过使用通用队列来实现您想要的,您可以从通用IEnumerable构造一个通用队列?旁注:您想要实现的示例(伪)代码可能会有帮助…@AlexC通用队列是一个好主意,但它会复制整个枚举以供编辑。通常,我在网络中使用这些行为在服务器端进行流解释,这是一种破坏交易的要求。