Search code examples
c#iostreamstreamreader

Passing a StreamReader object by Reference


I'm creating a small file parsing console app using C# in VS 2013. I'm using StreamReader to read in the file and creating objects from data in the file by parsing the lines.

I call a method, CreateHeader(), to create a Header object and pass the StreamReader object to read those particular lines, create a Header object, and return the object to the calling method. I'm passing the StreamReader object by reference because I'm wanting the StreamReader to be updated in the calling method to get the next line in the file where the CreateHeader() method left off. However, when the object is returned to the calling method, the StreamReader object wasn't updated and it still is at the same line in the file when the CreateHeader() method was called.

How would I pass a StreamReader object to another function and have that StreamReader be updated in the calling function? Here is some sample code:

static Header CreateHeader(ref StreamReader sr)
{
    Header hd = new Header();

    string formTitle = string.Empty;
    string[] words;
    string _line = string.Empty;;

    for(int x = 0; x < 5; x++)
    {
        _line = sr.ReadLine();
        Console.WriteLine(_line);
    }
}

static void ParseLines()
{
    Header _hd = CreateHeader(ref sr);
    _line = sr.ReadLine();
    prodList = new List<InventoryActivityProducts>();
}

Solution

  • First, the way you are using the StreamReader in your example (regardless of the ref) it should do what you are trying to achieve. Since you are not initializing the stream reader (sr) in your example, the error is probably in what you are not showing. In either case, the stream reader keeps a Position property internally that dictates where in the stream it should read next. Without modifying this property, the reader will simply continue where it left off.

    Second, this behavior is possible because the stream reader is a reference type. Without getting too deep, this means when you pass the instance of a reader to a method, it pass the address of where the method resides in memory (something like 0x0FA7230); this is in contrast to a value type, where the instance is passed by value (the actual value of the variable, like 4). Thus, when you call ReadLine on the stream reader, it is calling that method on the same instance as the outer method (thus why it should work as you intend). Using ref is a slightly different concept altogether (and unfortunate that it stands for reference). Passing a variable using ref (regardless of it being a reference or value type) will pass the address of the variable (note, not the address of the instance), or in effect an address of an address for reference types and an address to a value for value types. This is useful when you want to initialize a variable in an inner method and use the result in the outer method (effectively another way to return multiple values from a method); but other than that you will most probably not need to use it.