C# Serialize List

List type

A List can be serialized to the disk. We want to serialize (to a file) a List of objects. The next time the program runs, we get this List straight from the disk. We see an example of BinaryFormatter and its Serialize methods.

List

Example

Using keyword

This is the first part of the code example. We see a class in C# code, which you will want to put in a file called Lizard.cs. But you can also just put it in the same file. It adds several important namespaces in the using-statements.

Based on:

.NET 4

C# program that describes serializable type

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable()]
public class Lizard
{
    public string Type { get; set; }
    public int Number { get; set; }
    public bool Healthy { get; set; }

    public Lizard(string t, int n, bool h)
    {
	Type =    t;
	Number =  n;
	Healthy = h;
    }
}
Class: shapes

We see a class called Lizard, and it has three automatic properties. These store values and also are properties so are publicly accessible. The first constructor in the example accepts three values, a string, an int and a bool.

The Serializable attribute is specified right before the class definition. It tells the .NET Framework that the properties on this class can be written to a file and read back from.

Example 2

The second part of this tutorial is the Main method in your C# console program. It allows you to easily see how the data file is written to with BinaryFormatter, and how it is read from, deserialized.

C# program that serializes the type

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

// [Note: You can paste the Lizard class here] <--

class Program
{
    static void Main()
    {
	while(true)
	{
	    Console.WriteLine("s=serialize, r=read:");
	    switch (Console.ReadLine())
	    {
		case "s":
		    var lizards1 = new List<Lizard>();
		    lizards1.Add(new Lizard("Thorny devil",                1, true));
		    lizards1.Add(new Lizard("Casquehead lizard",           0, false));
		    lizards1.Add(new Lizard("Green iguana",                4, true));
		    lizards1.Add(new Lizard("Blotched blue-tongue lizard", 0, false));
		    lizards1.Add(new Lizard("Gila monster",                1, false));

		    try
		    {
			using (Stream stream = File.Open("data.bin", FileMode.Create))
			{
			    BinaryFormatter bin = new BinaryFormatter();
			    bin.Serialize(stream, lizards1);
			}
		    }
		    catch (IOException)
		    {
		    }
		    break;

		case "r":
		    try
		    {
			using (Stream stream = File.Open("data.bin", FileMode.Open))
			{
			    BinaryFormatter bin = new BinaryFormatter();

			    var lizards2 = (List<Lizard>)bin.Deserialize(stream);
			    foreach (Lizard lizard in lizards2)
			    {
				Console.WriteLine("{0}, {1}, {2}",
				    lizard.Type,
				    lizard.Number,
				    lizard.Healthy);
			    }
			}
		    }
		    catch (IOException)
		    {
		    }
		    break;
	    }
	}
    }
}

Output

s=serialize, r=read:
s
s=serialize, r=read:
r
Thorny devil, 1, True
Casquehead lizard, 0, False
Green iguana, 4, True
Blotched blue-tongue lizard, 0, False
Gila monster, 1, False
s=serialize, r=read:
Console screenshot

This code is mostly a command line program that allows you to type "s" to write a List of classes to a file, and "r" to read in that same List. It is fun to test the program in a console project.

When you press "s", a new List of Lizard objects is created. Five different Lizard objects are instantiated. Next, we wrap the file IO code in a try-catch block. This is important because file IO frequently throws.

Squares

And:The Stream is wrapped in a using block. The File.Open call attempts to open the new file for writing.

File.Open Examples

New BinaryFormatter instance. We simply call the Serialize method on the BinaryFormatter instance. This Serialize method receives the stream you want to write to, and also the object itself.

Deserialize. It again must use a Stream, which is wrapped in a using block for maximum efficiency and reliability. A new BinaryFormatter object is created, and it is used to get a new List<Lizard>.

Note:The Deserialize method, which accepts the Stream as a parameter, is slow but also powerful.

Finally:We write the List of Lizards it has read in from the file to the screen in a foreach-loop.

Foreach

Properties

Property

It is important to use properties, which have the get and set keywords, in this sort of serialization code. Properties have special metadata in the compiled code, which allows the base class library to use sophisticated logic.

Property

XML

Extensible markup language: XML

In this simple lizard example, using XML serialization might be best. This would generate a human-readable and editable data file, and would be more interoperable with web services.

XML

Summary

We saw a powerful way to serialize binary data to a file. We took a List generic instance with five objects in it, and serialized it efficiently. We employed the using statement for optimal clarity of the Stream code.


C#: List