将Stream转换为IEnumerable.如果可能的话,"保持懒惰"

Del*_*ted 12 c#

我收到一个Stream,需要将IEnumerable传递给另一个方法.

public static void streamPairSwitchCipher(Stream someStream)
{
    ...
    someStreamAsIEnumerable = ...
    IEnumerable returned = anotherMethodWhichWantsAnIEnumerable(someStreamAsIEnumerable);
    ...
}
Run Code Online (Sandbox Code Playgroud)

一种方法是读取整个Stream,将其转换为字节数组并将其传入,因为Array实现了IEnumerable.但是,如果我能以这样的方式传入它,以至于在传入之前我不必读取整个Stream,那就更好了.

public static IEnumerable<T> anotherMethodWhichWantsAnIEnumerable<T>(IEnumerable<T> p) {
    ... // Something uninteresting
}
Run Code Online (Sandbox Code Playgroud)

Phi*_*ier 14

这个按字节"按需"逐字节读取你的流:

public static IEnumerable<byte> streamAsIEnumerable(Stream stream)
{
    if (stream == null)
        throw new ArgumentNullException("stream");

    for (; ; )
    {
        int readbyte = stream.ReadByte();
        if (readbyte == -1)
            yield break;
        yield return (byte)readbyte;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者甚至更短,如果流为空,则不会引发异常,但不会产生任何结果:

public static IEnumerable<byte> streamAsIEnumerable(Stream stream)
{
    if (stream != null)
        for (int i = stream.ReadByte(); i != -1; i = stream.ReadByte())
            yield return (byte)i;
}
Run Code Online (Sandbox Code Playgroud)

  • 我假设你想要一个IEnumerable <byte>.如果你想要别的东西(例如IEnumerable <int>,IEnumerable <string>包含TextStream的所有行,......)让我知道. (2认同)

pli*_*nth 5

我做了一些实验并写了类似于phild的东西:

public static class ExtensionMethods
{
    public static IEnumerable<byte> Bytes(this Stream stm)
    {
        while (true)
        {
            int c = stm.ReadByte();
            if (c < 0)
                yield break;
            yield return (byte)c;
        }
    }

    public static IEnumerable<char> Chars(this TextReader reader)
    {
        while (true)
        {
            int c = reader.Read();
            if (c < 0)
                yield break;
            yield return (char)c;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的区别在于我将Bytes和Chars添加到Stream作为扩展方法,这让我可以这样编写:

foreach (char c in Console.In.Chars()) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

为了咧嘴笑,我编写了一个名为TokenizingStateMachine的抽象类,它在TextReader上使用IEnumerable来实现IEnumerable,这样一个简单的解析器可以做类似的事情:

foreach (Token t in stateMachine) {
}
Run Code Online (Sandbox Code Playgroud)