将控制台输入读为可枚举 - 一个语句?

时间:2012-03-18 07:42:05

标签: c# linq

使用C#/ .Net 4.0的标准功能,是否有更短/更好的方式在控制台中读取输入为可枚举?我认为没有任何实际用法,更多的是练习。

这就是我快速提出的关于“read array/filter it”的家庭作业问题的答案。基本上我试着编写File.ReadAllLines的控制台等等。

var completeConsoleInput = Enumerable.Repeat(0, int.MaxValue)
   .Select(i => Console.ReadLine()) 
   .TakeWhile(s => s != null);

我特别不喜欢我试图用作“永远”迭代器的Enumerable.Repeat(0, int.MaxValue),但我不记得看到其他选项了。

4 个答案:

答案 0 :(得分:13)

这是一个解决方案:

public static IEnumerable<string> ReadLines()
{
  string line;
  while(null != (line = Console.ReadLine()))
    yield return line;
}

public static void Main()
{
  string input = string.Join(ReadLines(), Environment.NewLine);
}

答案 1 :(得分:9)

You're not the first to try this,借助一个简单的扩展方法(类似于schglurps中的方法),您可以轻松地将其内联到LINQ查询中:

public static class TextReaderExtension
{
    public static IEnumerable<string> AsEnumerable(this TextReader reader)
    {
        string line;
        while ((line=reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}  

由于ConsoleInOut公开为TextReaderTextWriter,您只需使用Console.In.AsEnumerable()获取所有行即可在LINQ查询中。相同的扩展方法适用于任何TextReader

答案 2 :(得分:2)

我遇到了同样的问题,但我一直在寻找更通用的解决方案。理想情况下,我想扩展System.Linq.Enumerable类,但由于这是不可能的,我不得不把它放在另一个类中。

实现:

public static class MyEnumerable
{
    public static IEnumerable<TResult> Repeat<TResult>(Func<TResult> func)
    {
        for (;;)
        {
            yield return func();
        }   
    }
}

用法示例:

var completeConsoleInput = MyEnumerable.Repeat(Console.ReadLine)
                                       .TakeWhile(s=> s != null);

答案 3 :(得分:0)

这个怎么样?

// One line to read them all
var lines = Console.In.ReadToEnd().Split(new[]{Environment.NewLine}, StringSplitOptions.None);

用法:

Console.WriteLine(lines.Length + " lines:");
foreach (var line in lines) Console.WriteLine(line);

在读取所有行之前,你不会得到IEnumerable,类似于File.ReadAllLines;但它是一个使用标准C#功能的单线程:)