Live data from Hacker News

Things in C# you might have missed

fekberg.com

1–10 of 12 posts

Re: Things in C# you might have missed

#2
C# has a lot of these little things, that can make you struggle until you discover them.

But beware with yield-return, you have to be very conscious of the execution model of LINQ. Take for example this piece of code:

    IEnumerable Readlines(Stream io)
    {
        while(io.CanRead)
        {
           io.Read(buffer, 0, bufferLength)
           ... do things with buffer and get a line...
           yield return line;
        }
    }
    
    IEnumerable ReadFileLines(string filename)
    {
        IEnumerable lines
        using(FileStream file = new FileStream(filename))
        {
           lines = ReadLines(file);
        }
        return lines;
    }
This would always fail and throw an exception. Why? When you call ReadLines, the actual object that is returned is not the list of strings. ReadLines is not executed until that list is not enumerated. ReadFileLines opens the stream, passes it as an argument and then closes the stream. When you enumerate that list, ReadLines will start and try to access a closed stream, which causes an exception. Read more here: http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-...

EDIT: Another problem that you could face with deferred execution is that you could execute a method multiple times without noticing.

    var lines = ReadLines(file);
    var count = lines.Count();
    var text = lines.Aggregate("", (acc, x) => x + acc);
This would read all the lines two times (one for count and another for aggregate), and would probably throw another exception because the EOF had been reached in the first execution. In other situations you could have a ultra-slow function because you're executing a heavy function with yield-return multiple times.

This is not a problem of yield-return on itself (as SideburnsOfDoom says, it's as easy as calling ToList()), but should remind you that using yield-return everywhere instead of lists is not a good idea.

Re: Things in C# you might have missed

#4
post #2

C# has a lot of these little things, that can make you struggle until you discover them. But beware with yield-return, you have to be very conscious of the execution model of LINQ. Take for example this piece of code: IEnumerable Readlines(Stream io) { while(io.CanRead) { io.Read(buffer, 0, bufferLength) ... do things with buffer and get a line... yield return line; } } IEnumerable ReadFileLines(string filename) { IE…

I guess you'd fix that by doing this?

   lines = ReadLines(file).ToList();
ToList() is the go-to method to force eager evaluation of a lazy enumeration.

Re: Things in C# you might have missed

#8
post #2

C# has a lot of these little things, that can make you struggle until you discover them. But beware with yield-return, you have to be very conscious of the execution model of LINQ. Take for example this piece of code: IEnumerable Readlines(Stream io) { while(io.CanRead) { io.Read(buffer, 0, bufferLength) ... do things with buffer and get a line... yield return line; } } IEnumerable ReadFileLines(string filename) { IE…

I guess you'd fix that by doing this? lines = ReadLines(file).ToList(); ToList() is the go-to method to force eager evaluation of a lazy enumeration.

Of course, but you can only do that if you know that ReadLines is using yield-return. If this method were to be used by other people you should use a temporary list to read all the stream before returning from the method; it's the expected behaviour.

Re: Things in C# you might have missed

#9
In 2012, using bit shifting in your code for multiplication or division by powers of 2 is a bad idea. It makes the intent of your code less obvious and it's not always safe (think 2's complement negative numbers). The compiler or the JITter will make this optimization for you when it's appropriate.

Re: Things in C# you might have missed

#10
post #8

Earlier quoted context omitted.

I guess you'd fix that by doing this? lines = ReadLines(file).ToList(); ToList() is the go-to method to force eager evaluation of a lazy enumeration.

Of course, but you can only do that if you know that ReadLines is using yield-return. If this method were to be used by other people you should use a temporary list to read all the stream before returning from the method; it's the expected behaviour.

Not just yield return. In quite a few different circumstances LINQ will return an IEnumerable that is a wrapper over a query that won't be executed until you try and pull results out of it. LINQ Queries can wrap database queries, http results, active directory, file system or anything else.

And as you note, enumerating it twice can mean doing the underlying query twice, with potentially differing results.

Post reply on HN