The Need for LINQ
At first, when I didn't understand LINQ, I couldn't appreciate why we needed (or why anyone wanted) it. LINQ seemed very limited in usefulness, and I, like many of my colleagues, bashed it in ignorance. Now, due to understanding the semantics and benefits of the language, I've come to love it and wonder how I lived without it.LINQ does not allow us to do anything new, as far as functionality goes. Really, if you wanted to make the argument of a 'real programmer', you could do all of this same functionality by writing encyclopedias of C code (heck, might as well just write it in assembly for "performance" reasons). But, LINQ does create a new way of looking at enumerations of data, and gives out-of-the-box functionality for them.
I realize that the above paragraphs might seem vague, so I'll get right into real examples that I have used as well as some odd examples that you might not have thought about as being 'queryable objects'.
Baby Steps - Basic LINQ Queries
Let's look at some very simple examples of LINQ so that we can have a basis to grow on. Let's pretend that we have a user control that has a variable amount of TextBoxes added to it (based on some database query or whatever). Our user control might have other controls (Buttons, Literals and the like), and we want to disable all of the TextBoxes if the user doesn't have security permissions to edit these controls. Please keep in mind that this is a hypothetical scenario at this point just so we can see some basic LINQ (in this case, LINQ to Objects).Now, you can do this a few ways. Because the number of TextBoxes is dynamic we would possibly do something like this:
The above code isn't really that bad, but I for one don't like that I have to loop through all of my controls, check the type, cast it to the type that I just checked for, and then set my property. So, let's see how LINQ will not only "pretty up" my code, but will also make more sense to us programmers:// Loop through all of the controls.
foreach (Control myChildControl in this.Controls)
{
// Make sure the control is a TextBox.
if (myChildControl is TextBox)
{
// Cast that "Control" object to a TextBox and disable it.
((TextBox)myChildControl).Enabled = false;
}
}
This LINQ approach is much cleaner. It's clear from the start that you want to work with a list of TextBoxes only. Secondly, you aren't type checking, then re-type casting. Now, you might argue that you could avoid the second type-cast by using an "as" keyword and checking for nulls, or you could say that you don't like how many lines of code this takes. Those are some valid claims, but if you are thinking that, then apparently you have a short attention span (as I mentioned above that this is just to get you a little familiar with the language syntax).// Define a enumeration only containing child TextBoxes.
var myChildTextBoxes = from myChildControl in this.Controls
where myChildControl is TextBox
select myChildControl;
// Loop through my TextBoxes.
foreach (TextBox myChildTextBox in myChildTextBoxes)
{
// Disable the TextBox.
myChildTextBox.Enabled = false;
}
Step Two - Querying Unconventional Data Sources
Once you begin to use LINQ a bit more in you're C# (or VB), you'll begin to think of 'data sources' in a different way. For instance, you may see a directory (a folder on your computer) as a data source of files. You can even start to look at your list of running processes as a data source. Really, no enumeration is safe!What if you were to make a web application that allowed you to upload and download files from your home machine? Let's say you had a DropDownList that would show a list of the files in the specified directory, perhaps with a button that lets you download it. How would you go about populating that DropDownList with clean file names for the "Text" property and perhaps the path for the "Value" property? I'll go a step further and say that this is what you're DropDownList looks like in ASP.NET:
Well, you could create you're own custom class that has a FileName property and a FullPath property. Then you could make a generic list of that class, loop through the files in a Directory.GetFiles method, add an entry for each file, set the list as the DataSource of the DropDownList and data bind. That's a whole lot of nasty that I'm not even going to show the code for (really, because I never want to write nasty code like that again). Here's what I would do using LINQ:<asp:DropDownList ID="MyFilesList" runat="server"
DataTextField="FileName" DataValueField="FullPath" />
All I can say after that is "Go LINQ GO!" and of course "case closed!"// Set the DataSource of our DropDownList to an enumeration of a new
// "anonymous type" (meaning a class that is being built on the fly)
// that contains the file names and full paths in our directory.
this.MyFilesList.DataSource = from file in Directory.GetFiles(somePath)
select new
{
FileName = Path.GetFileName(file),
FullPath = file
};
// Call the "DataBind" method :P
this.MyFilesList.DataBind();
Extension Methods and Lambda Expressions
One more part to LINQ is the heavy use of Extension Methods and Lambda expressions to accomplish this beautiful language enhancement. If you remember our original example of disabling the TextBoxes, then you're going to love one of the 50 STANDARD OPERATORS that are brought to you just by including a reference to the System.Linq namespace! Check this out:Don't check you're MSDN... there is no method called "OfType" on the ControlCollection class. But, because the ControlCollection class implements the IEnumerable interface, it automatically gets all of the extension methods that LINQ has kindly given to any enumeration (such as "OfType" which I am using above).// Loop through my TextBoxes.
foreach (TextBox myChildTextBox in this.Controls.OfType())
{
// Disable the TextBox.
myChildTextBox.Enabled = false;
}
LINQ can be done one of two ways (or a combination of both): query expressions or method expressions. The difference between the two is only a syntax difference, as they ultimately compile into the same thing. Example:
Lambda expressions come into play when you want to perform another standard operation such as "SUM" or "MAX". Here's an example that I have used recently. I wanted to make a property that displayed the "TotalBill" of an object that had child "orders" in it. Here's how lambda helped out:// This line of code...
var textBoxes = from control in this.Controls
where control is TextBox select control;
// is the same thing as this.
var textBoxes = this.Controls.OfType();
If you're not quite familiar with lambda as of yet, you can get a better explaination of the above in a blog post I made not long ago: LINQ, Lamda and Extension Methods Work Together!public decimal TotalBill
{
get
{
// Keep in mind that "Orders" is just a list of
// 'Order' objects and has no special functionality.
return this.Orders.Sum(order => order.Price);
}
}
No comments:
Post a Comment