Saturday 19 December 2015

C# CSV Library and HTTP Handlers

A colleague and I was recently looking at some old ASP.NET WebForms code which generated a potentially large CSV string and returned it in a response to a HTTP request. The original code was placed in a standard ASP.NET WebForms page in the OnLoad event handler. As the code was working with the HttpResponse object and writing the CSV directly to the HTTP output stream, we determined that this code was better placed in a HTTP Handler. The primary advantage of using a HTTP handler to generate the file is that we can bypass the unnecessary ASP.NET WebForms page life cycle.

The existing code was using a StringBuilder to generate the CSV string in the page OnLoad event handler. As you may imagine, this looked messy and was a pain to maintain. To abstract the CSV string creation logic, my colleague introduced me to a useful CSV library called LINQ to CSV. The project page link for this library is here and the library is available as a NuGet package.

The LINQ to CSV library enabled us to decorate some properties in a model class with attributes that specify how to output the property in CSV form. The example below (from the library project page) shows how to apply the attributes:

public class Product
{
    [CsvColumn(Name = "ProductName", FieldIndex = 1)]
    public string Name { get; set; }
    [CsvColumn(FieldIndex = 2, OutputFormat = "dd MMM HH:mm:ss")]
    public DateTime LaunchDate { get; set; }
    [CsvColumn(FieldIndex = 3, CanBeNull = false, OutputFormat = "C")]
    public decimal Price { get; set; }
    [CsvColumn(FieldIndex = 4)]
    public string Country { get; set; }
    [CsvColumn(FieldIndex = 5)]
    public string Description { get; set; }
}

Once your model class is decorated, you can then use other classes of the library to generate a CSV representation of a collection containing your model instances. This representation can be output to disk as demonstrated in the code example below:

IList<Product> products = new List<Product>();
products.Add(
    new Product
    {
        Name = "Samung Galaxy S6",
        LaunchDate = DateTime.Today,
        Price = 500,
        Country = "United Kingdom",
        Description = "This is a Samsung phone product"
    }
);

products.Add(
    new Product
    {
        Name = "Apple iPhone 5",
        LaunchDate = DateTime.Today,
        Price = 600,
        Country = "United States",
        Description = "This is an Apple phone product"
    }
);

CsvFileDescription inputFileDescription = new CsvFileDescription();
inputFileDescription.SeparatorChar = ',';
inputFileDescription.FirstLineHasColumnNames = true;

CsvContext csvContext = new CsvContext();
csvContext.Write(products, @"C:\Products.csv");

Usefully, the CsvContext class of the library also supports an overload to the Write method which accepts a TextWriter stream. Passing a TextWriter stream to this overload results in the library outputing the CSV representation to your stream rather than a file on disk. In our case, we used a StreamWriter that wrote to a MemoryStream. Once the CSV file content was in the MemoryStream instance, we sent the stream contents in the HTTP response from the HTTP handler. The full HTTP handler code is below (using the example product data).

public class ProductsExportHandler : IHttpHandler
{
    public bool IsReusable { get { return true; } }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.AddHeader(
            "content-disposition"
            "attachment;filename=BulkExport.csv"
        );
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.ContentType = "application/vnd.text";

        IList<Product> products = new List<Product>();
        // Add products...
            
        var inputFileDescription = new CsvFileDescription();
        inputFileDescription.SeparatorChar = ',';
        inputFileDescription.FirstLineHasColumnNames = true;
            
        using (var memoryStream = new MemoryStream())
        {
            using (var streamWriter = new StreamWriter(memoryStream))
            {
                var csvContext = new CsvContext();
                csvContext.Write(products, streamWriter);
                    
                streamWriter.Flush();
                    
                context.Response.BinaryWrite(memoryStream.GetBuffer());
            }
        }
    }
}

Sunday 6 September 2015

Practice Test Driven Development with C# Exercises on Exercism.io

I was recently introduced to Exercism.io which is a place where you can download a number of C# exercises to work on. Exercism.io not only supports C# but also other programming languages. Each exercise comes with a pre-written suite of unit tests and it is your task to implement the required functionality in order to make the unit tests pass.

The exercises are a good way to get familiar with Test Driven Development (TDD) without having to write the tests. You can still semi-follow the prescribed red-green-refactor approach, where you initially have a test that fails, you then write an implementation to make the test pass and then you refactor your implementation until you're happy with it.

The Exercism.io website provides a useful command line interface tool which you use to fetch exercises and then also submit your solutions. Once a solution is submitted, it is made available on Exercism.io for others to "nitpick". This is a great feature where others who have done the same exercise can view your solution and suggest improvements. Although I've found the C# community on Exercism.io to be fairly quiet (with only a few people nitpicking), I can see this being a very useful feature once more people start to use the site.

If you've also heard of Project Euler (which I blogged about here), then yes, Exercism.io is similar in principle, but there are differences which you'll find quickly after trying both sites. I've tried a few exercises in the C# section of Exercism.io - they are fun and a good to practice your C#/.NET framework knowledge. Highly recommend this site to anyone who enjoys small programming exercises in their spare time and anyone who is interested in trying TDD. You can get started here.

Tuesday 25 August 2015

Conway's Game of Life: An Exercise in WPF, MVVM and C#

This blog post was written for the Lockheed Martin Insight blog, sharing here for the external audience.

Last month I started the Pluralsight summer camp by watching an interesting video in which the presenter implements Conway's Game of Life using HTML, CSS and JavaScript. The video inspired me to write an MVVM based implementation of the game using Windows Presentation Foundation (WPF) and C#. There were two aims to this exercise. The primary was for me to reacquaint myself with WPF, which is a framework I've been wanting to spend some time with for a while. And the secondary was to implement something fun.

The purpose of this blog post is to document the exercise. We'll cover what Conway's Game of Life is, a bit about the design and then see how some WPF and .NET framework features help in implementing an MVVM solution. The source code for the implementation is available on GitHub.

So, what is Conway’s Game of Life?

The Game of Life is a popular cell automaton algorithm that simulates the evolution of life. The algorithm was designed by British mathematician John Conway and has gained popularity for its simplicity. In its purest form, the universe for the Game of Life is represented by a grid which has an infinite number of cells. Each grid cell can contain a dead or living cell. The game starts with the user providing a seed generation of living cells. Based on the initial generation of cells, the universe evolves through generations to simulate evolution. For a generation to evolve, the following four rules are applied to the current generation:

  1. Any live cell with fewer than two live neighbours dies (due to under-population).
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, (due to overcrowding).
  4. Any dead cell with exactly three live neighbours becomes a live cell (by reproduction).

And that's it. By applying these four rules, it is surprising to see how a universe can evolve to create complex symmetrical patterns, even when there is no symmetry or pattern in the seed generation.

Arriving at an Object-Oriented Design

The MVVM architectural design pattern was adopted to achieve a clear separation of concerns. I started by identifying the models:

  • Cell Model: Represents a single cell in the universe. Encapsulates data for the cell's position and whether it is dead or alive.
  • Generation Model: Represents a generation of life. Encapsulates data on the size of the universe, the cells within the universe and provides functionality to alter the living state of cells.

The EvolutionEngine class was identified to hold the current generation and take on the responsibilities of:

  • Evolving the current generation to the next generation, as per the rules of evolution.
  • Detecting if the current generation can no longer evolve.
  • Keeping track of the number of generations that the current generation has evolved through.
  • Resetting the generation back to an empty state.

A single view-model was identified, namely, GenerationViewModel. The view-model uses the EvolutionEngine class to:

  • React to actions that originate from the view.
  • Provide information for the view to display.
  • Provide notifications to the view if the observed information changes.

In summary, we have a couple of models, an engine class to work with the models and a view-model to keep the view in sync with the models.

Writing the MVVM WPF Implementation

The following diagram illustrates how the components of an MVVM solution are related in WPF (image source).

A view is built using the eXtensible Application Markup Language (XAML). The association between a view and its view-model is accomplished through the DataContext property of the view. Controls in a view are bound to properties in the view-model using the data binding features of WPF. In a scenario where the view-model is only serving as a proxy between the view and model, you may consider the use of a view-model superfluous and let the view-model expose the underlying model (see the "Why Use a ViewModel?" section in an MSDN article). Actions performed on the user interface are encapsulated in commands that are exposed by the view-model (using the Command design pattern). We will see how a view-model exposes its supported commands using the ICommand interface. Finally, notifications are raised as C# events from the view-model. The INotifyPropertyChanged interface is used primarily for this purpose.

As I’ve alluded to, there are a number of useful features in WPF and .NET that assist in the implementation of an MVVM solution. The particular features that I’m referring to are:

  • The FrameworkElement.DataContext property.
  • Using the Binding class to associate parts of the view to the view-model.
  • Raising notifications through the INotifyPropertyChanged interface.
  • Converting incompatible data between bound properties using the IValueConverter interface.
  • Encapsulating and executing actions using the ICommand interface.

Each of these features were used in the implementation for the game. In the sections below, we will discuss what each of these features are and see examples of how they were adopted in the solution.

Setting the Data Context and specifying a Binding

The Grid control was a natural choice to visually represent the universe. Each cell of life within the universe is represented by a TextBlock control. The code snippet below shows how the TextBlock is created:

In WPF, user interface controls derive from the FrameworkElement class which contains an important property named DataContext. The DataContext property of a control is set to an object that the control uses to pull its data from and/or push its data to. This object is typically a view-model or model instance. By setting the TextBlock.DataContext property to an instance of the Cell model we can bind properties of the TextBlock control to properties of the Cell model.

Aside: As a WPF view is hierarchical, a nice feature of using the DataContext property is that it can be inherited from a parent user interface control.

In our Game of Life implementation, we use the Background (colour) property of the TextBlock control to indicate whether the cell is dead or alive. On lines 7-10 of the CreateCellTextBlock method, you’ll see that we call the SetBinding method. The first parameter to this method specifies which property we want to set the binding for (made possible with Dependency Properties) and the second parameter accepts a Binding instance.

The Binding instance is created by the following method:

There are a few things to note here. Firstly, the Binding object supports a Source property which we do not explicitly set. The reason for this is that if no Source property is set on a binding, the binding defaults to using the DataContext property on the control that the binding is set on. In this case, the TextBlock control’s DataContext property is already set to a Cell model instance. We can therefore set the Path property to point to a particular property within the model, in this case the boolean Cell.Alive property.

The Mode property is set to the enumeration value of BindingMode.TwoWay, meaning that any change to the TextBlock control through the user interface updates the model and conversely any change to the model updates the user interface. To support two-way binding, the Cell model will need to implement the INotifyPropertyChanged interface so that any change to the Alive property is notified to the view.

Implementing Notifications with INotifyPropertyChanged

The INotifyPropertyChanged interface is implemented by classes that need to notify clients (in our case, the view) that an observed property value has changed. Typically, this interface is implemented by view-models or models that want to broadcast changes to certain property values.

INotifyPropertyChanged supports one member, the PropertyChanged event. If you have a two-way binding setup between a user interface control property and a view-model property, programmatic changes to the view-model property will not be reflected in the user interface unless the view-model implements INotifyPropertyChanged and the observed property’s setter raises the PropertyChanged event.

In our solution, we wrote a reusable ObservableBase class that implements INotifyPropertyChanged. The Cell and GenerationViewModel classes both inherit from ObservableBase.

The PropertyChanged event is raised from the OnPropertyChanged method which accepts a single parameter – the name of the property that has changed. The CallerMemberName attribute is used so that we can call this method without having to specify a hardcoded string with the property name. The code below shows the implementation for the Cell model, which inherits from ObservableBase.

Notice how the Alive property setter calls the OnPropertyChanged event. An unfortunate side effect of implementing INotifyPropertyChanged is that you’re unable to use automatic properties for the properties that need to raise the notification event.

Converting Between Bound Properties Using IValueConverter

In our earlier code snippet for the CreateCellAliveBinding method, you may have noticed that we also set the Binding.Converter property. The Converter property is used when we bind two properties that have a type mismatch or expect data in different formats. To recap, we are using the Background (colour) property of the TextBlock to indicate if the cell represented by the TextBlock is dead or alive. The Alive property on our Cell model is of boolean type, therefore, we need our binding to convert the boolean value to a colour. This is where the IValueConverter interface is used to take on the role of an adapter.

The implementation of the IValueConverter is in the class LifeToColourConverter, shown below:

The IValueConverter interface supports two methods, namely, Convert and ConvertBack. The Convert method is used when binding the value from the source property (Cell.Alive) to the target property (TextBlock.Background). Conversely, the ConvertBack method is used when updating the source from the target. If you are only using one-way binding, then you are only required to provide an implementation for the Convert method (the ConvertBack method can safely throw the NotImplementedException).

Handling User Interface Actions Using the Command Design Pattern

A view-model exposes a set of actions that are encapsulated within commands. Commands are exposed as properties on the view-model so that user interface controls can bind to them. The logic for a command is encapsulated within a class that implements ICommand. The ICommand interface supports two methods; CanExecute and Execute. The CanExecute method returns a boolean value which determines whether the command can execute. The Execute method contains the command logic to run.

In our solution, the view's DataContext is set to an instance of the GenerationViewModel class. In this view-model, we expose the following three commands:

RelayCommand is a popular implementation of the ICommand interface which has been available as open source for some while. We are using a particular variant of RelayCommand which enables a single parameter to be sent to the method that ultimately executes the command. You can view how the three command properties are initialised and the implementations for the CanExecute/Execute methods in the GenerationViewModel class.

An advantage of the RelayCommand implementation for ICommand is that it achieves reusability by using the Predicate and Action delegates to reference the CanExecute and Execute methods respectively. This avoids the need for writing a separate ICommand implementation for every command that the game supports.

In the user interface for the game, we have two buttons. One button binds to the view-model EvolveCommand property and the other binds to the ResetCommand property. The XAML snippet below shows how the command bindings are created:

If the ICommand.CanExecute method returns false for a command that is bound to a button, the button is automatically disabled.

The ToggleCellLifeCommand is executed when the user is setting up the initial generation of living cells, the binding for this command is setup programmatically by the following method (called by the CreateCellTextBlock method shown earlier):

We are using the InputBinding class to specify that a left mouse click on the TextBlock should execute the ToggleCellLifeCommand and pass it a formatted string that contains the cell position. The ToggleCellLifeCommand method implementation in the GenerationViewModel class looks up the cell and toggles the Alive property boolean value. As we have an active binding between each TextBlock and its Cell.Alive property, the TextBlock colour will automatically change to a colour that represents the current value for the Alive property.

Summary

In this post, we’ve introduced and described some of the main features that WPF and the .NET framework provide for implementing MVVM based solutions. Conway’s Game of Life served as a fun exercise to use these features with.

We saw how the FrameworkElement.DataContext property enables seamless binding between user interface controls and properties on view-models. Two-way binding was shown to be possible using the INotifyPropertyChanged interface as a mechanism to notify the view of changes in the view-model. We introduced a useful ObservableBase class which implements INotifyPropertyChanged and can be reused in future WPF projects that need to support two-way binding. To bind two properties that work with different data types, we saw how an implementation of the IValueConverter interface can be used as an adapter. Finally, we saw how the command pattern is used to encapsulate logic in an ICommand implementation and how commands are exposed as properties on a view-model that can be bound-to in the view.

The animated graphic below shows the finished game. In the animation, we see the evolution for a simple L-shaped seed pattern in a universe of 25x25 cells. Surprisingly, this basic seed pattern lives through eighteen generations of life with some fascinating symmetrical patterns before it stops evolving.

Full source code is available in a GitHub repository.

Wednesday 15 July 2015

Using Gacutil on a Non-Development Server

A short while ago I came across an issue with using the Visual Studio gacutil tool on a non-development server. By non-development server, I mean a system which does not have Visual Studio installed on it with the associated .NET Software Development Kit (SDK). I thought it may be useful to share the problem and solution here in case anyone else runs into the same issue.

The gacutil tool is part of the Visual Studio SDK and is used to install a strongly named assembly to the Global Assembly Cache (GAC). In my case, I had written a .NET 4 class library which was to be consumed by an application which lives on the same machine. As part of my deployment testing, I used the gacutil tool through the Visual Studio Developer Command Prompt to install the assembly in my local GAC. The result was successful as shown in the screenshot below.


I then had to install the same class library in the GAC of a test server. The test server had .NET Framework version 4 installed but because it doesn't have Visual Studio installed, it did not have the Developer Command Prompt and gacutil on the server. I then located the gacutil.exe and gacutil.exe.config files from my laptop file system, the location in my case was:

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools

I copied the gacutil.exe and gacutil.exe.config files onto the test server and opened command prompt (cmd.exe) as administrator. Running the gacutil install command yielded no success response from gacutil, as shown in the screenshot below.


Surprisingly, gacutil gave no feedback as to what happened. After doing a bit of online research, I learned that gacutil has a dependency on a dll file named "gacutlrc.dll". In my laptop file system, I found this dependency in the folder location:

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\1033

I then created a folder named "1033" in the same directory that I copied gacutil.exe to on my test server. I copied the "gacutlrc.dll" file into the 1033 folder and executed the gacutil install command with a successful result.

In summary, if you are using the gacutil command on a non-development server, ensure you have the following in a single folder:
  • gacutil.exe and gacutil.exe.config
  • a folder named "1033" with the gacutlrc.dll file within it
It should then just be a case of opening a command prompt window as an administrator, navigating to the directory containing gacutil.exe and running the gacutil /i [path to assembly] command.

Sunday 3 May 2015

Implicit vs. Explicit Interface Implementation

One feature of C# that I find useful is the support of implicitly or explicitly implementing interfaces. For example, if we have a simple interface such as the following:
public interface IDoSomething
{
    void DoIt();
}
You are probably already aware that we can implicitly implement the interface with code like:
public class MyClass : IDoSomething
{
    public void DoIt()
    {
        throw new NotImplementedException();
    }
}
We can use the implementation like:
MyClass myClass = new MyClass();
myClass.DoIt();
If MyClass is to explicitly implement the interface, the MyClass implementation would look like:
public class MyClass : IDoSomething
{
    void IDoSomething.DoIt()
    {
        throw new NotImplementedException();
    }
}
Notice the two differences.
  1. The access modifier has been dropped from the DoIt method signature
  2. The DoIt method name is now qualified with the interface name
So how does this now affect how we use MyClass? Well, you can no longer call the DoIt method on a direct instance of MyClass, you are now forced to code to the interface to access the DoIt method. So our previous code which instantiates MyClass and calls DoIt will no longer compile. Instead you will need to "explicitly" work with an instance of the interface to access the DoIt method. One example would be by declaring the type of the object to be the interface, like the following:
IDoSomething myClass = new MyClass();
myClass.DoIt();
Or you could cast the MyClass instance back to its interface to call the DoIt method, as shown in the following snippet:
MyClass myClass = new MyClass();
((IDoSomething) myClass).DoIt();
So, what are the benefits of explicitly implementing an interface?
  • As the implementer of a class, you can try to force good practice on clients by making them code to an interface
  • As a consequence of the point above, you can reduce tight coupling in your code as it shouldn't be using concrete implementations directly
  • If you are implementing two interfaces which have the same method signatures, or a method signature in an interface clashes with one already visible in your class, you can separate the two methods

Saturday 2 May 2015

Microsoft Exam 70-483: Programming in C#

Earlier this week I took and passed the Microsoft 70-483 exam. In this post, I'll provide some insight into my preparation.

The 70-483 exam tests your knowledge on the C# programming language and the .NET framework. In this case, it was C# 5 and the .NET Framework version 4.5. By passing this exam, you earn the Microsoft Specialist certification.
 
The official Microsoft page for the exam can be viewed by clicking on this link. I took the exam in the UK. It should be noted that the 70-483 exam is also the first exam on the path for the MCSD Windows Store Apps certification, which is ultimately the certification that I'm aiming for. 
 
As described on the official 70-483 exam page, the exam is broken down into four main areas:
  • Managing program flow
  • Creating and using types
  • Debugging applications and implementing security
  • Implementing data access

Under each of these topics on the exam page, you get a detailed breakdown of what is covered. There is a plethora of resources on the web that you can use to prepare for this exam (blogs, MSDN, PluralSight etc.). I recommend watching the exam prep video on the exam page first - this sets the scene in more detail and gives you a better idea about the topics covered on the exam.
 
As the two guys mention on the Microsoft prep video, there is no substitute for actual practice. At the beginning of my preparation, I created a blank console application in Visual Studio and added to this as I revised various topics. I wrote a method for each particular language construct or .NET framework class that I wanted to further understand. In each method, I practiced using a particular construct/class by referring to the MSDN site for the topic. I found this approach useful in clarifying how something works - the code produced also served as a useful reminding aid when the exam date got closer (the brain recalled those "eureka" moments that I had when writing the code). LINQPad is also a useful tool for practicing.
 
I found the official Microsoft exam reference book by Wouter de Kort useful (Amazon link here). Although the book shouldn't be used as a definitive resource, it serves as a useful aid in introducing various topics which you then should build upon with your own further research. I particularly found the multithreading, cryptography and managing assemblies sections of the book a worthwhile read.
 
I also bought the practice tests from MeasureUp. The practice tests were useful to get a feel for question formats - which are a mixture of multiple choice (sometimes with more than one correct choice) and drag and drop type questions. You can also loosely simulate test conditions by running the MeasureUp tests in "certification mode" - meaning that you are timed and unable to see the answers as you progress in the test. Note that the actual exam format/time can differ compared to the MeasureUp practice certification mode tests.
 
Finally, ensure you read the website of the test centre. In the UK, Microsoft has appointed the PearsonVUE test centres. I found the videos on the PearsonVUE website useful in telling me what to expect on the day (security procedures, the software used for the exam itself and what I need to bring with me on the exam day).
 
If you're taking this exam, all the best and feel free to leave a comment about your experiences!

Wednesday 15 April 2015

C# How To: Using Implicitly Typed Arrays

Implicitly typed arrays allow the C# compiler to determine the most appropriate type for an array. The selected type is based on the values you initialise the array with. This useful feature was introduced in C# 3.0.
var intArray = new [] { 1, 2, 3 };
var stringArray  = new [] { "hello""world"null };
var nullableIntArray = new [] { 1, (int?)2, 3 };

Console.WriteLine(intArray.GetType());
Console.WriteLine(stringArray.GetType());
Console.WriteLine(nullableIntArray.GetType());

// Following results in a compile-time error:
//    "No best type found for implicitly-typed array"
var notGoingToWorkArray = new [] { "hello", 1, 2f };

Friday 16 January 2015

C# How To: CSV to List or List to CSV

The following code snippet shows how to convert from a CSV string to a List using the string class Split method.

const string ColoursCsv = "red,blue,green,yellow";
                        
List<string> coloursList = ColoursCsv.Split(',').ToList();

The following code snippet shows how to convert from a list to a CSV string using the string class Join method.

List<string> coloursList = new List<string> { 
    "red"
    "blue"
    "green"
    "yellow" 
};

string coloursCsv = string.Join(",", coloursList);

C# How To: Convert to Convert String to Int

To convert from a string to an integer type you can use the Convert class as shown in the code snippet below. The Convert class contains a large number of static methods which allow you to convert from one type to another.

string numberString = "1985";
int number = Convert.ToInt32(numberString);

Monday 12 January 2015

C# How To: Start a Program/Process

To start a program in C#, you can use the Process class. The Process class has a static method called Start which accepts a filename as a parameter. The example below shows how easy it is to start Microsoft Notepad from a C# application. Remember to include the "using System.Diagnostics;" directive at the top.

const string ProgramPath = "Notepad";

Process.Start(ProgramPath);

Note that if you need to start a program which accepts command line arguments, then you can use an overload of the Start method which accepts a ProcessStartInfo object. The following snippet shows how to open a file within notepad from your C# application.

const string ProgramPath = "Notepad";

Process.Start(new ProcessStartInfo
    {
        FileName = ProgramPath,
        Arguments = @"C:\WriteTest.txt"
    }
);

Sunday 11 January 2015

C# How To: Create Text File And Write To It

Continuing with my new C# "how-to" theme, the code snippet below shows how to create a text file and write content to it using the StreamWriter class. Remember to add the "using System.IO;" directive at the top. Note that there is a StreamWriter constructor which supports a Boolean parameter "append" - if you pass true for this parameter and the file already exists, the StreamWriter will append content to the file rather than overwrite the existing content.

const string TextFilePath = @"C:\WriteTest.txt";

using (StreamWriter writer = new StreamWriter(TextFilePath))
{
    writer.WriteLine("Hello, world");
    writer.WriteLine("Bye, world");
}

C# How To: Read a Text File

This is the first of a series of C# "how to" posts. The following C# code snippet shows how to read a text file line-by-line using the StreamReader class. Remember to add the "using System.IO;" directive as this is the namespace which the StreamReader class is in.

const string TextFilePath = @"C:\ReadTest.txt";

using (StreamReader reader = new StreamReader(TextFilePath))
{
    string currentLine;

    while ((currentLine = reader.ReadLine()) != null)
    {
        Console.WriteLine(currentLine);
    }
}