Tech Off Thread

6 posts

Need C# help

Back to Forum: Tech Off
  • User profile image
    cSharp4me

    Hello everyone,

     

    I was going through Bob Tabors  C# instructional videos, which is fantastic btw. Anyway, I'm a little confused with this one. On the following code, within the while loop, there is an if (line != null) statement . Why is this statement necessary? Doesn't the While loop set the same condition? I tried it without the if (line != null) statement, and it produces a blank window when the program is run. Any help would be appreciated.

    Here is the source code --

     

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.IO;

    namespace ReadTextFileWhile

    {

    classProgram

    {

    staticvoid Main(string[] args)

    {

    StreamReader myReader = newStreamReader("Values.txt");

    string line = "";

    while (line != null)

    {

    line = myReader.ReadLine();

    if (line != null) //why is this necessary? This sets the same condition specified on the while loop.

     

    Console.WriteLine(line);

    }

    myReader.Close();

    Console.ReadLine();

    }

    }

    }

     

  • User profile image
    wkempf

    The line before the if statement sets the 'line' variable. That happens after the check in the while statement. This means 'line' could have been set to null, and so you need to recheck the value before using it. You could eliminate the double check with some reworking of the code.

    string line = myReader.ReadLine();
    while (line != null)
    {
        Console.WriteLine(line);
        line = myReader.ReadLine();
    }

  • User profile image
    Sven Groot

    Basically, due to the nature of the ReadLine method you either have to duplicate the check or duplicate the call to ReadLine (which is what wkempf did above).

    I do find the original code a bit strange, however. If you're going with the duplicate check, I'd use a do-loop rather than a while-loop to eliminate the redundant check on the first iteration:

    string line;
    do 
    {
        line = myReader.ReadLine();
        if (line != null)
        {
            // do stuff
        }
    } while (line != null);

    Note that it's possible to get rid of the duplication entirely, though it's debatable how readable the end result is:

    string line;
    while ((line = myReader.ReadLine()) != null)
    {
        // Do stuff
    }

    Ultimately the nicest way (if you're reading from a text file):

    foreach (string line in File.ReadLines("values.txt"))
    {
         // do stuff
    }

    Which also means you don't have to worry about properly disposing the StreamReader (which the code in the OP doesn't do). Note that File.ReadLines should not be confused with File.ReadAllLines, since the latter reads the entire file into memory and should therefore be avoided.

  • User profile image
    wkempf

    , Sven Groot wrote

    Which also means you don't have to worry about properly disposing the StreamReader (which the code in the OP doesn't do).

    Actually, it does. It calls myReader.Close(), which is synonymous with Dispose. It does it poorly however, because no consideration was made for exceptions being thrown (either a finally block or a using block should be used). Maybe that's what you meant by "properly"?

  • User profile image
    Sven Groot

    , wkempf wrote

    *snip*

    Actually, it does. It calls myReader.Close(), which is synonymous with Dispose. It does it poorly however, because no consideration was made for exceptions being thrown (either a finally block or a using block should be used). Maybe that's what you meant by "properly"?

    Yes, that's what I meant. Smiley

  • User profile image
    Sven Groot

    To follow up a little, this is genuinely something that I struggle with. I understand the need to keep example code simple. I understand the need not to overwhelm learners with too many new concepts at once. But I'm also of the opinion that this leads to people learning bad habits. C++/Win32 sample code is especially guilty of this; error handling in C++ (if not using exceptions like when you're using Win32 or COM) is so verbose that it nearly always gets omitted from sample code, and how many bugs in released products are caused because someone ignored an error somewhere they shouldn't have?

    In this particular case I'd probably be in favour of just including the using statement even if it isn't explained. Even if there's just a note saying "trust us, you need to do this whenever you deal with some things like streams, we'll explain why later." That may not be the best approach, but I think it's better than creating a sample for someone to copy that does the wrong thing. And since the sample does include a call to Close, it's clearly not averse to teaching the concept of having to close a file. All it needs to do is say "the using statement makes sure the file is closed no matter what, even if your program crashes" which should be fairly clear even if you haven't explained exceptions yet.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.