views:

84

answers:

2

Is there a better way to write this extension method?

public static class StreamReaderExtensions
{
    public static StreamReader SkipLines(this StreamReader reader, int lines)
    {
        for (var i = 0; i < lines; i++)
        {
            reader.ReadLine();
        }

        return reader;
    }
}

I was thinking something like:

int linesToSkip = 3;
linesToSkip.Do(reader => reader.ReadLine());

Or:

int linesToSkip = 3;
linesToSkip.Do(() => reader.ReadLine());

But what would Do() look like?

+6  A: 

Try using the power already defined in LINQ. Use this extension method to read the lines:

public static IEnumerable<string> ReadLines(this StreamReader reader)
{
    while (!reader.EndOfStream)
    {
        yield return reader.ReadLine();
    }
}

Then, given you have an open StreamReader, your code can look like this:

int linesToSkip = 3;
var lines = reader.ReadLines().Skip(linesToSkip);

Enjoy.

Enigmativity
+1 nice solution.....:-)
Pramodh
+1 - I was writing the exact same suggestion as you posted your answer.
Fredrik Mörk
I'd just note that the usual idiom for ReadLine is `string line; while ((line = reader.ReadLine()) != null) { ... }`.
Porges
@Porges: Just because that is a common idiom doesn't make it easy to read. I prefer my conditional loop tests to *test a condition* rather than read a line from a file, mutate a variable, and test a condition. Reworking the code to make the condition simpler is a good idea.
Eric Lippert
A: 

Take a look at this article from Eric Lippert.

He gives this example to implement such an extension:

public static class FileUtilities
{
    public static IEnumerable<string> Lines(string filename)
    {
        if (filename == null)
            throw new ArgumentNullException("filename");
        return LinesCore(filename);
    }

    private static IEnumerable<string> LinesCore(string filename)
    {
        Debug.Assert(filename != null);
        using(var reader = new StreamReader(filename))
        {
            while (true)
            { 
                string line = reader.ReadLine();
                if (line == null) 
                   yield break;
                yield return line;
            }
        }
    }
}

If have have this functionality just use the normal power of LINQ by using things like Skip(), SkipWhile(), TakeWhile(), etc.

Oliver