我收到了一个Stream,需要将IEnumerable传递给另一个方法。
public static void streamPairSwitchCipher(Stream someStream)
{
...
someStreamAsIEnumerable = ...
IEnumerable returned = anotherMethodWhichWantsAnIEnumerable(someStreamAsIEnumerable);
...
}
一种方法是读取整个Stream,将其转换为字节数组并将其传入,因为Array实现了IEnumerable。但如果我能以这样的方式传入它,以至于在传入之前我不必阅读整个Stream,那就更好了。
public static IEnumerable<T> anotherMethodWhichWantsAnIEnumerable<T>(IEnumerable<T> p) {
... // Something uninteresting
}
答案 0 :(得分:13)
这个按需“逐个字节”地读取你的流:
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;
}
}
甚至更短,如果流为空,则不会引发异常,但只会产生任何结果:
public static IEnumerable<byte> streamAsIEnumerable(Stream stream)
{
if (stream != null)
for (int i = stream.ReadByte(); i != -1; i = stream.ReadByte())
yield return (byte)i;
}
答案 1 :(得分: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;
}
}
}
这里的区别在于我已经将Bytes和Chars添加到Stream作为扩展方法,这让我可以这样写:
foreach (char c in Console.In.Chars()) { /* ... */ }
对于笑话,我写了一个名为TokenizingStateMachine的抽象类,它在TextReader上使用IEnumerable来实现IEnumerable,这样一个简单的解析器可以做类似的事情:
foreach (Token t in stateMachine) {
}