How to Use LINQ to Query a Collection of Objects in .NET 3.5
One of the cool new features in .NET 3.5 is LINQ, which stands for Language Integrated Query. It allows you to use a syntax similar to SQL to query datasources, XML, and objects. In this posting, we will use a subset of LINQ called LINQ to Objects to query a collection of objects.
Let's start with the class of object we'll be querying. For this example, we'll use a very simple class called Spaceship. Spaceship has two properties: Name, which is the name of the ship, and CrewCount, which is the number of crew members it has. It also overrides the ToString() method to return a string which gives the ship's name and crew count. Here's what the class looks like:
(Shameless plug: the code samples in this post were formatted for HTML with my HTML Encoder program, which you can download here)
/// <summary>
/// A class representing a spaceship
/// </summary>
class Spaceship
{
private int miCrewCount;
private string msName;
/// <summary>
/// The name of the spaceship
/// </summary>
public string Name { get { return msName; } }
/// <summary>
/// The number of crew members the spaceship has
/// </summary>
public int CrewCount { get { return miCrewCount; } }
/// <summary>
/// Constructor
/// </summary>
/// <param name="ShipName">The name of the spaceship</param>
/// <param name="CrewCount">The number of crew members in the spaceship</param>
public Spaceship(string ShipName, int CrewCount)
{
miCrewCount = CrewCount;
msName = ShipName;
}
/// <summary>
/// Returns spaceship info in string format
/// </summary>
/// <returns>The name and crew count of the spaceship</returns>
public override string ToString()
{
return "Spaceship " + msName + " - Crew Count = " + miCrewCount.ToString();
}
}
Now for the fun part. In the code below, we create a generic List of type Spaceship, then add a bunch of Spaceship objects to it. Then, we query the collection to get just the Spaceships with a CrewCount of 300 crew members or less. I'll explain how this works in a moment.
List<Spaceship> lstShips;
try
{
lstShips = new List<Spaceship>();
lstShips.Add(new Spaceship("Enterprise", 430));
lstShips.Add(new Spaceship("Reliant", 300));
lstShips.Add(new Spaceship("Excelsior", 550));
lstShips.Add(new Spaceship("Daedalus", 200));
lstShips.Add(new Spaceship("Apollo", 200));
lstShips.Add(new Spaceship("Prometheus", 200));
lstShips.Add(new Spaceship("Millennium Falcon", 2));
lstShips.Add(new Spaceship("Home One", 700));
var ships = from smallship in lstShips
where smallship.CrewCount <= 300
select smallship;
foreach(Spaceship ship in ships)
{
Console.WriteLine(ship.ToString());
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message,
"An error has occurred",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
lstShips = null;
}
The output this code produces is as follows:
Spaceship Reliant - Crew Count = 300
Spaceship Daedalus - Crew Count = 200
Spaceship Apollo - Crew Count = 200
Spaceship Prometheus - Crew Count = 200
Spaceship Millennium Falcon - Crew Count = 2
Here's how it works. Let's examine the LINQ query:
var ships = from smallship in lstShips
where smallship.CrewCount <= 300
select smallship;
LINQ queries begin with the from clause. Our from clause states from smallship in lstShips. lstShips is the name of our generic list, whereas smallship is used to inspect the values of the ships, as shown in the where clause. Our where clause states where smallship.CrewCount <= 300 -- we only want Spaceships with a crew of 300 or less. Finally, our query says select smallship, which tells the query engine to select the object when the criteria is met. The results of the query are placed in a variable called ships, which is declared as type var. This is part of the new type inference in .NET 3.0. The variable is still strongly typed, but we're leaving it up to the compiler to determine the type when the code is compiled.
After the query is run and we have our new subset of Spaceships in our ship collection, we use a standard foreach loop to call the ToString() method of each object to display its information.
This is a simple example, and just the tip of the iceberg, but you can probably see where LINQ can come in handy.
Let's start with the class of object we'll be querying. For this example, we'll use a very simple class called Spaceship. Spaceship has two properties: Name, which is the name of the ship, and CrewCount, which is the number of crew members it has. It also overrides the ToString() method to return a string which gives the ship's name and crew count. Here's what the class looks like:
(Shameless plug: the code samples in this post were formatted for HTML with my HTML Encoder program, which you can download here)
/// <summary>
/// A class representing a spaceship
/// </summary>
class Spaceship
{
private int miCrewCount;
private string msName;
/// <summary>
/// The name of the spaceship
/// </summary>
public string Name { get { return msName; } }
/// <summary>
/// The number of crew members the spaceship has
/// </summary>
public int CrewCount { get { return miCrewCount; } }
/// <summary>
/// Constructor
/// </summary>
/// <param name="ShipName">The name of the spaceship</param>
/// <param name="CrewCount">The number of crew members in the spaceship</param>
public Spaceship(string ShipName, int CrewCount)
{
miCrewCount = CrewCount;
msName = ShipName;
}
/// <summary>
/// Returns spaceship info in string format
/// </summary>
/// <returns>The name and crew count of the spaceship</returns>
public override string ToString()
{
return "Spaceship " + msName + " - Crew Count = " + miCrewCount.ToString();
}
}
Now for the fun part. In the code below, we create a generic List of type Spaceship, then add a bunch of Spaceship objects to it. Then, we query the collection to get just the Spaceships with a CrewCount of 300 crew members or less. I'll explain how this works in a moment.
List<Spaceship> lstShips;
try
{
lstShips = new List<Spaceship>();
lstShips.Add(new Spaceship("Enterprise", 430));
lstShips.Add(new Spaceship("Reliant", 300));
lstShips.Add(new Spaceship("Excelsior", 550));
lstShips.Add(new Spaceship("Daedalus", 200));
lstShips.Add(new Spaceship("Apollo", 200));
lstShips.Add(new Spaceship("Prometheus", 200));
lstShips.Add(new Spaceship("Millennium Falcon", 2));
lstShips.Add(new Spaceship("Home One", 700));
var ships = from smallship in lstShips
where smallship.CrewCount <= 300
select smallship;
foreach(Spaceship ship in ships)
{
Console.WriteLine(ship.ToString());
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message,
"An error has occurred",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
lstShips = null;
}
The output this code produces is as follows:
Spaceship Reliant - Crew Count = 300
Spaceship Daedalus - Crew Count = 200
Spaceship Apollo - Crew Count = 200
Spaceship Prometheus - Crew Count = 200
Spaceship Millennium Falcon - Crew Count = 2
Here's how it works. Let's examine the LINQ query:
var ships = from smallship in lstShips
where smallship.CrewCount <= 300
select smallship;
LINQ queries begin with the from clause. Our from clause states from smallship in lstShips. lstShips is the name of our generic list, whereas smallship is used to inspect the values of the ships, as shown in the where clause. Our where clause states where smallship.CrewCount <= 300 -- we only want Spaceships with a crew of 300 or less. Finally, our query says select smallship, which tells the query engine to select the object when the criteria is met. The results of the query are placed in a variable called ships, which is declared as type var. This is part of the new type inference in .NET 3.0. The variable is still strongly typed, but we're leaving it up to the compiler to determine the type when the code is compiled.
After the query is run and we have our new subset of Spaceships in our ship collection, we use a standard foreach loop to call the ToString() method of each object to display its information.
This is a simple example, and just the tip of the iceberg, but you can probably see where LINQ can come in handy.
Comments
Post a Comment