Archive

Archive for the ‘.NET 3.5’ Category

Visual Studio 2008 Setup Project Frustrations

March 4, 2008 28 comments

I have not needed to create a Setup project since installing VS2008, but this afternoon I needed to share a utility program with a coworker friend of mine (who is not technical), so I opened the solution and added a Setup and Deployment project. Everything seemed to be fine. I added the primary output of my application’s project and adjusted the company name and product name properties, as well as some other settings, just like I used to do in VS2005.

The problem occurred when I wanted to create Start Menu and Desktop shortcuts for the application. In VS2005, double clicking the Application Folder would show you the list of DLLs, EXEs, and other files that would be installed. You could right-click the main project output file and create a shortcut to the program, which could then be copied to the User’s Desktop and User’s Program Menu directories. And you could also add icons and assign them to the shortcuts.

This was what I wanted to do in VS2008, but double clicking on the folders in File System does nothing. As a result, you cannot select the output file as instructed in the MSDN documentation. This is very frustrating: the Setup and Deployment project has always worked well for me (these are internal distribution installers), but now with VS2008 it no longer appears to function properly. The resulting MSI did work and did install the software, but without an icon and without shortcuts in the desired locations.

If you know the solution for this, please leave a comment. If I find a solution to this, I’ll be sure to share it. For now, all I can do is share the pain.

Trudging through ASP.NET

February 19, 2008 Comments off

I just wanted to post a quick update on what’s going on in my world this week.? I posted last week about my Authorize.Net efforts (which I updated this morning).? That work is the precursor to finally learning ASP.NET, one of my New Year’s Resolutions.? I have to admit that I have always assumed that learning ASP.NET would be no big deal.? I have developed web sites in PHP, JSP and Servlets, and even RPG CGI, so what could be so hard about ASP.NET?

Well, the short answer is that it is not hard, however I find myself constantly frustrated because I feel like I have to relearn all the basics.? Seemingly simple matters take me a lot of time and investigation to get working.? I’m sure that if I was learning from scratch this would be no problem, but in my case I am hobbled by too much knowledge going in.? In other words, my brain keeps getting in the way.

So I am trudging through books, websites, and training materials.? Currently, I am reading through Sitepoint.com’s “Build your own ASP.NET 2.0 Web Site“, which appears to be the simplest material I have on hand.? I’m also planning on spending some time going through some beginners videos at asp.net.? And if all that fails, I’ll consider ordering again from TotalTraining.com. I know one day soon I’ll look back on this and wonder what all the fuss was about, but for now I must simply “Soldier On!”

Upgrade your C# Skills part 5 – LINQ to XML

January 31, 2008 7 comments

I am working on a project that requires a configuration file that can be edited or even replaced by the user. Looking at the requirements, what I really need is a series of “records” of the same layout, similar to a database table. Naturally, given the current state of technology, an XML file is the obvious choice. So I decided that now would be a good time to investigate LINQ to XML.

Understanding LINQ to XML

First of all, unlike other LINQ topics, this one is not really query oriented. LINQ to XML (also known as XLINQ) is primarily about reading and writing XML files. Once read into program variables, you can use LINQ to Objects technologies to perform query functions.

First, the XLINQ classes are not part of the standard System.Linq namespace. Instead, you will need to include System.Xml.Linq. This namespace contains the XML classes that make XLINQ worthwhile, and we’ll review a few of these as we go along.

Second, this article will be a far cry from exhaustive on the subject: there are a ton of additional features and topics that I will not cover. Chief among the reasons for this is that I am far from an XML expert. I consider myself a typical developer where XML is concerned: my programs need to find and consume information stored in an XML format. I may even have occasion to update or write XML content. Otherwise, XML holds no particular glamor for me.

Reading an XML File

Most articles I have read on this topic begin with using XLINQ to create XML structures and files. My first task was to read an existing XML file, so that is where I will begin.

Here is the XML data I will be using for this article:


<LayoutItems Class="">
  <LayoutItem Name="FullName">
    <Row>2</Row>
    <Column>5</Column>
  </LayoutItem>
  <LayoutItem Name="Address1">
    <Row>3</Row>
    <Column>10</Column>
  </LayoutItem>
  <LayoutItem Name="Address2">
    <Row>4</Row>
    <Column>10</Column>
  </LayoutItem>
  <LayoutItem Name="City">
    <Row>5</Row>
    <Column>10</Column>
  </LayoutItem>
  <LayoutItem Name="State">
    <Row>5</Row>
    <Column>40</Column>
  </LayoutItem>
  <LayoutItem Name="Zip">
    <Row>5</Row>
    <Column>44</Column>
  </LayoutItem>
</LayoutItems>

This is a simple configuration file for a printing product I am writing. The root element LayoutItems has a Class attibute and contains a collection of child LayoutItem objects. Each LayoutItem has a Name attribute that references a Property name in the Class listed in the LayoutItems Class attribute. Each LayoutItem element then contains Row and Column elements. I’m pretty confident you can guess what these represent. This is a simple example, but no matter how complex your XML layout is, these same techniques will work.

First, we need to get an object that we can use to read and process our XML data. There are two that we can use: XDocument and XElement. If we use XDocument, we have to pull an XElement out of it to use our data, so an easier solution is to bypass the XDocument altogether and just use the XElement approach.

There are several ways to create a usable XElement object. This example uses XElement’s static Load method. In this case I am passing it the path of the XML file:

// Load XML from file
XElement xml = XElement.Load(XmlPath);

Dropping into debug after this happens shows us that the XElement object now contains all the XML from our file. All the nodes in an XElement are represented by other XElements. This nesting may look confusing at first, but it makes sense, like the Nodes of a TreeNode. Each subsequent element contains all the information for that element, including any other child elements. In our simple example there is only one sublevel of elements, but again the same techniques would work regardless of how deeply nested your data.

Now, in order to read through my XML data, I am going to loop through the Elements collection:

// Loop through Elements Collection
foreach (XElement child in xml.Elements())
{
    // Process child XElement
}

Each of these XElement objects will represent one LayoutItem section. The LayoutItem element has a Name attribute that I need to read, so I am going to use the XElement’s Attribute property:

// Read an Attribute
XAttribute name = child.Attribute("Name");

There is also an Attributes property that is a collection of all the XAttribute objects. If you had multiples to process or did not know the attribute names, this would be a simple enough option to use.

I want to point out that frequently the methods ask for an XName value. You will quickly find though that XName has no constructor. According to the documentation, wherever an XName is asked for, sending a string will perform an implicit conversion and create an XName object. I’m sorry, but this is really stupid: it creates unnecessary confusion in Intellisense and is not clear or intuitive. All that being said, now that you know, whenever you see “XName”, think “string”.

Now, since I have no further nesting to deal with, I’m ready to go ahead and read my child element data. The code is very similar to the Attribute code, except now we are using the “Element” property:

// Read an Element
XElement row = child.Element("Row");
XElement column = child.Element("Column");

Now that we have our Attributes and Elements, it’s time to actually use the values. To do this, we need to extract the values out of our XElement object. To accomplish this, you have two options. First, you can always use ToString() to get the string representation of the data and then manually convert to the desired type:

// using ToString() to extract data
string val = row.ToString();
float realVal = Convert.ToSingle(val);

Another option that will let you bypass that step is to use one of the built in cast operators to get the appropriate type directly:

// using a built in Cast operator
float realVal = (float)row;

There are built in cast operators for all the expected cast of characters like int, bool, DateTime, etc.

Creating and Writing XML

I used Visual Studio to create my XML file, but writing XML is pretty straightforward as well. Essentially, you need to create XElement objects and add other XElement objects to their Elements collection. Let’s create the above document in code.

The XElement constructor has several overloads. To just create an XElement, you can simply create a new one and pass it the name of the Element:

// Create a new XElement
XElement root = new XElement("LayoutItems");
// Add an Attribute
root.Add(new XAttribute("Class", ""));

Now, what would be intuitive would be able to access the Attributes and Elements collections and use their Add() methods to add content to them. Unfortunately, this is not possible because these are Read-only collections. XElement has an Add method of its own that accepts single content objects or a params[] construct. You can also use this method on the constructor, so let’s use the constructor method to create a few new XElements and add them to our root:

// Create and add more elements
XElement elm1 = new XElement("LayoutItem",
    new XAttribute("Name", "FullName"),
    new XElement("Row", 2),
    new XElement("Column", 5));
root.Add(elm1);

XElement elm2 = new XElement("LayoutItem",
    new XAttribute("Name", "Address1"),
    new XElement("Row", 3),
    new XElement("Column", 10));
root.Add(elm2);

XElement elm3 = new XElement("LayoutItem",
    new XAttribute("Name", "Address2"),
    new XElement("Row", 4),
    new XElement("Column", 10));
root.Add(elm3);

XElement elm4 = new XElement("LayoutItem",
    new XAttribute("Name", "City"),
    new XElement("Row", 4),
    new XElement("Column", 10));
root.Add(elm4);

XElement elm5 = new XElement("LayoutItem",
    new XAttribute("Name", "State"),
    new XElement("Row", 5),
    new XElement("Column", 40));
root.Add(elm5);

XElement elm6 = new XElement("LayoutItem",
    new XAttribute("Name", "Zip"),
    new XElement("Row", 5),
    new XElement("Column", 44));
root.Add(elm6);

Debug will now show that our root XElement object now contains all the properly formatted XML. To write it to the file system, you can use the standard StreamWriter options, or you could use the built in Save() method:

// Write file
root.Save("myFileName.xml");

In this example, I am just passing the string of the path of the file I want. There are several other overloads, but I’m confident you will be able to use them with no problem.

Conclusions

Like I said at the beginning, you didn’t see any query features here, because in this case the LINQ parts really happen in the XML processing. The Attributes and Elements collections implement IEnumerable<T>, so if you need to query them you can do so using LINQ to Objects techniques.

Personally, these new classes finally make XML an attractive solution. I finally feel like reading and processing XML can be pain free and straightforward. I know that I will be using a lot more XML in the future as a result.

Categories: .NET 3.5, C# 3.0

I hate being sick…

January 28, 2008 Comments off

I caught a bug that has been terrorizing the office and I’ve been out sick since last Wednesday.? I got back in today and found my DVD copy of Total Training for Microsoft Expression Studio waiting my return.? Hopefully I’ll begin going through the training this week, and naturally I’ll give you all a review of the materials and products.

Also, I’ve been working on a Printing Framework,Maker nextel tracfone ringtones software. so I plan on writing a series of articles on Printing.

Finally, I’ll be speaking next week at RVNUG on the new .NET 3.5 C# features.? I’ll cover most of the material from the “Updgrade your C# Skills” series, so if you are there be sure to say “Howdy!”

Categories: .NET 3.5, C# 3.0, Expression

A Good, practical LINQ example

January 17, 2008 14 comments

You may recall that one of my New Year’s Resolutions was to find and participate in a .NET Forum. Well, I have joined several, and have even posted a few times. While perusing the C# Corner forums today, I found this post about not being able to break out of a loop. The code was using one of my favorite techniques for Windows Forms, the ErrorProvider. I like ErrorProvider and use it quite a bit, and I have done what the poster was trying to do many times: loop through the Controls on a Form and find out whether any of them have an active error message. If they do, then I use that information to warn the user or set some Form state so that it is apparent that an error exists.

My answer does not specifically address the issue the poster brought to the table, but the post got me to thinking: we should be able to use LINQ to solve this problem. Here is a typical example of the loop construct:

bool hasErrors = false;
foreach (Control c in this.Controls)
{
    if (!"".Equals(errorProvider1.GetError(c)))
    {
        hasErrors = true;
        break;
    }
}

In looking at this, it appears we have a good case for using LINQ: we have a Collection and we want to query that Collection for information about itself. Seems it should be pretty straightforward, and ultimately it is, but in this particular case it took a little trial and error to hack it out. Since it wasn’t as simple as I originally thought it would be, let’s walk through it in stages.

Build a Queryable Object

The first step is to try and build a LINQ query of all the Controls on the Form:

var q = from c in this.Controls
        select c;

When I tried to compile this, I got an error I did not expect:

Could not find an implementation of the query pattern for source type ‘System.Windows.Forms.Control.ControlCollection’. ‘Select’ not found. Consider explicitly specifying the type of the range variable ‘c’.

Naturally, I reexamined the code and couldn’t find anything odd about it, but what did seem odd was that I knew this.Controls was a Collection, and LINQ is supposed to work on Collections, right? Wrong!

Getting a Sequence from a Collection

If you read my recent LINQ to Objects post you may recall that LINQ does not work on Collections, but rather Sequences. It soon dawned on me that ControlCollection does not qualify as a Sequence because it does not implement IEnumerable<T>, but rather IEnumerable. This led me to uncharted territory: how do I get an IEnumerable<T> from an IEnumerable? Well, there was definitely some trial and error, and a lot of IntelliSense browsing, but I finally figured out an elegant solution.

Microsoft was gracious enough to provide an IEnumerable extension method (my favorite new feature) that will cast an IEnumerable to an IEnumerable<T>. Fittingly, this method is named Cast<T>(). Here is the code that will transform our ControlCollection into a usable Sequence:

var q = from c in this.Controls.Cast<Control>()
        select c;

Now we have a LINQ query object representing all the Controls on our Form.

Querying the Queryable Object

Now that we have a Sequence instead of a Collection to work with, this could come in quite handy. In fact, this would be a good candidate for a ControlCollection Extension Method in its own right. In the meantime, now that we have a queryable object, we have several options for how to complete our task. One way is to query the entire Sequence when we need it. I’m going to use our friend the Lambda Expression to find out if there are any Controls with Errors in the errorProvider:

// Query as needed
MessageBox.Show(q.Count(c => !"".Equals(errorProvider1.GetError(c))) > 0 ? "There are errors!" : "No errors!");

Again we are using a supplied Extension Method called Count<>() and passing it a Func<> defined by our Lambda Expression. If the count is greater than 0, then we have errors, else we do not.

This approach is especially handy if you may need to query the list in multiple ways. In our case, however, we know that this criteria is the only one we will need, so we have the option to embed our Lambda in the LINQ statement itself. To do so, we will use yet another Extension Method called Where:

var q = from c in this.Controls.Cast<Control>()
        .Where(c => !"".Equals(errorProvider1.GetError(c)))
        select c;

You’ll notice that this is the same logic just implemented as part of the LINQ statement. Now our consuming code is a bit simpler because our list is defined as only the items with messages in the ErrorProvider:

// Now we don't need the Lambda
MessageBox.Show(q.Count() > 0 ? "There are errors!" : "No errors!");

Here is the complete code block:

var q = from c in this.Controls.Cast<Control>()
        .Where(c => !"".Equals(errorProvider1.GetError(c)))
        select c;
MessageBox.Show(q.Count() > 0 ? "There are errors!" : "No errors!");

Hopefully, as you experiment with these new features, you will come to appreciate how they all complement each other. This example turns out to be fairly simple, even though it took a little effort to work through. In it, we have taken advantage of Extension Methods, LINQ, and Lambda Expressions because they all work together. While these are all great additions on their own, the cumulative power they represent is outstanding. I guess .NET really is worth more than the sum of its parts.

Expression Web Review

January 15, 2008 Comments off

My copy of Microsoft’s “Web Solutions Toolkit”, a special offer alloted to Microsoft Action Pack Subscribers, arrived yesterday. Among other items, the toolkit includes a complete copy of the Microsoft Expression Suite. I installed the Suite and have begun experimenting with Expression Web, and I wanted to share some of it with you.

Right off the bat, the toolkit includes a license key for a 60 day free pass to Total Training Online for Expression Web. I have seen a couple of Total Training videos before, and I am impressed with their quality. I spent a couple hours this morning watching training videos specifically for Expression Web and then this afternoon I developed my first web site using the tool.

I have built probably two dozen web sites over the years. I have made static pages, CGI data driven sites, Servlets and JSPs, and PHP sites. Over the last five years or so, I have focused on XHTML, CSS2, and PHP. More recently than that, I have grown weary of web development. I no longer get excited about web pages, and when people ask me to help with them I rarely accept. Part of this may be because I have always been a WordPad kind of a guy (unless I’m on Linux, where I prefer VI). What can I say, in this area I have always been a bit old fashioned. I like the hands on control it affords me. As an answer to my lost desire to create web sites, over the last year or so I have become a WordPress advocate: if I can’t do it in WordPress, I’m just not interested.

Well, all that is about to change. Expression Web is a fantastic tool. It includes an incredible set of features that are easy to find and easy to use. I find it as intuitive as a complex piece of software could be, and I am very impressed with the CSS editing facilities. Equally impressive are the preview options. Here are some of the other highlights:

  • Web sites can be created from predefined templates
  • You can create and save your own templates
  • Dynamic Web Templates allow you to implement and update the look and feel of an entire site (not the same as ASPX Master Pages)
  • You can create ASPX pages (including Master Pages) – even though you cannot write C# or VB in Expression Web, you can use it to easily create the pages which can then be consumed by Visual Studio. This can even include Data Binding code.
  • If you are into that sort of thing, you can create Tables and Frames. Meh.
  • You can create pages using Absolute Positioning or Relative Positioning
  • The Absolute Positioning tools blow ASPX and Visual Studio out of the water
  • The software includes a ton of templates for CSS layout, pages, tables, even entire web sites

The interface is very similar to Visual Studio, so if you are a VS user you should feel right at home with Expression Web. If you are new to Web design, I think this would be a great way to get your feet wet. If you are an old hat, I think you will understand and love this tool in a matter of minutes. In either case, it is definitely evaluating.

Also worth evaluating is Total Training. I have no interest in their company whatsoever, but so far I like what I see, and they have training available for the entire suite for under $300. I think I’ll be a customer in the very near future. As I learn more, I will certainly share.

Categories: .NET 3.5, Expression

Automatic Properties and StackOverflowException

January 14, 2008 2 comments

I’ve written a couple of times before about Automatic Properties, a tiny little feature that I have really come to enjoy. Remember that an Automatic Property looks something like this:

// An Automatic Property
public string FirstName { get; set; }

I’ve also written that if you want to add any behavior to this property, then you must create a variable and complete the code just as you would have a regular property. I was coding the other day and I had to transform add some behavior to what had been an automatic property. For grins, I wanted to see what I could get away with, so I tried a couple of different approaches.

First, I really only wanted to add behavior to the Setter, so I tried leaving the Getter as is:

// Will not compile
public string FirstName
{
    get;
    set
    {
        FirstName = value.TrimEnd(new char[] { ' ' });
    }
}

This will not compile, resulting in the following error:

‘ConsoleTestBed.Person.FirstName.get’ must declare a body because it is not marked abstract, extern, or partial

OK, so no joy there, I have to fill out the Getter. But notice in the Setter block there is no error! So I fill out the Getter and it looks like this:

// This compiles
public string FirstName
{
    get { return FirstName; }
    set
    {
        FirstName = value.TrimEnd(new char[] { ' ' });
    }
}

This compiles just fine. What I’m hoping at this point is that the Compiler will recognize what I am doing (given its context) and still create the variable for me. However, when I run it, I get a StackOverflowException. What you have probably figured out, and what I was afraid of, is that by referencing the Property name within the Property, I have created a recursion problem. So, unfortunately, I was originally correct: in order to make these changes work, I have to create a variable to support the Property:

// This compile AND works
private string _firstName;
public string FirstName
{
    get { return _firstName; }
    set
    {
        _firstName = value.TrimEnd(new char[] { ' ' });
    }
}

So if your program throws a StackOverflowException on a Property, be sure that you haven’t created a Recursion issue. Maybe someday the C# compiler guys can find a way to make this work based on the Context, or maybe a Property Attribute.

Categories: .NET 3.5, C# 3.0

Extension Methods Update

January 2, 2008 Comments off

I’ve been working on some more Extension Method stuff (I’ll be sharing soon!), and in the process I updated the DevelopingForDotNet.Extensions namespace.? Here is a list of the updated methods:

  • DateTime.GetDateString() – accepts an Enum for the format of the DateTime string (Enum is part of the namespace).? Overridden to allow control over the separator character.
  • DateTime.TwoDigitYear() – returns the Year of the DateTime in two digit format.? Great for aligning with legacy data.
  • IDictionary.ExecuteOnValues<K, V>() – performs an Action<V> on each Value in a Dictionary.
  • decimal.ConvertToMoney() – Converts any decimal to a two decimal precision numeric.? Overridden to allow control over rounding behavior.
  • decimal.GetMoneyString() – Converts a decimal to Money and returns a properly formatted string.
  • decimal.GetUSMoneyString() – implements the above, but specific to US Currency.? Also overridden for rounding.
  • long.ConvertToWords() – converts a long value to spelled out words.
  • decimal.GetDecimalNumbers() – returns just the decimal portion to the right of the decimal point as an integer.
  • StringBuilder.Clear() – clears all text from a StringBuilder (sets its length to 0).

Be sure to download the update.? Keep watching, there will be more to come.

Categories: .NET 3.5, C# 3.0, Free Code

Upgrade your C# Skills part 4 – LINQ to Objects

January 2, 2008 7 comments

If you’ve been following along recently, you’ll know that I have immersed myself in VS2008 and .NET 3.5. No discussion of these new technologies would be complete without addressing LINQ (Language Integrated Query). My problem is that LINQ has been written about to death by a lot of more qualified people than myself. With the other articles in this series I felt like I had something to offer, but here I am not so sure. So here is what I will do: I will hit the lowlights. Instead of showing you how to use LINQ, which you can get just about anywhere, I’m going to focus on when and why to use LINQ. I’ll also show you how to write your own Types that can be consumed by LINQ.

LINQ actually comes in five flavors:

  • LINQ to Objects – using LINQ to query Collections.
  • LINQ to SQL – using LINQ to directly query SQL Server databases.
  • LINQ to Datasets – using LINQ to query disconnected data stored in a DataSet.
  • LINQ to XML – using LINQ to create, read, manage, and query XML formatted data.
  • LINQ to Entities – using LINQ to query databases via the Entity Data Model Framework.

In this article, I will only cover LINQ to Objects as it provides the foundation for all the others. I will most likely cover LINQ to SQL and LINQ to DataSets in future articles. I have never been much of an XML user, but I may become one with the power of LINQ to XML: if I do, I will write about that at the appropriate time. Same goes for LINQ to Entities: the Entity Data Model Framework should be released sometime in the spring, and I will probably wait until then to cover that topic. So enough of me telling you what I’m not going to write about: let’s get to the real material.

IEnumerable<T>

I teach a weekly class on C# and .NET at my company to a group of procedural programmers, and every time I say something like “IEnumerable of T” I get back a bunch of blank stares. IEnumerable<T> is a generic interface that is implemented by every generic collection type in .NET. It is important to note that this is different from IEnumerator<T>, which we will not be implementing, at least not directly.

IEnumerable<T> is a pretty simple interface. In fact, it only exposes two methods, each called GetEnumerator() – one is generic and one is not. These methods return an IEnumerator<T>, which is just the default looping mechanism for the Collection. You’ll see this implemented in code later in this article.

For now, I want to stress that IEnumerable<T> is really what makes the magic of LINQ work. Anything that implements this interface (or one of its descendants) is queryable by LINQ. For a little terminology, we are going to use the term sequence to refer to anything that implements IEnumerable<T>. This is more accurate than Collection since there are Collections that do not implement this interface. So the answer to the question “When can I use LINQ to Objects?” is “You can use LINQ to Objects against any Sequence”.

Why use LINQ

So now that you know when you can use LINQ, lets talk about why using it is a good idea. Let’s revisit our old favorite, the Person class:

class Person
{
    public event EventHandler<maritalstatuschangedeventargs> MaritalStatusChangedEvent;
    private char _maritalStatus;

    public Person()
    {
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string DOB { get; set; }
    public bool IsMilitaryVeteran { get; set; }
    public char MaritalStatus
    {
        get
        {
            return _maritalStatus;
        }

        set
        {
            if (_maritalStatus != value)
            {
                _maritalStatus = value;
                if (MaritalStatusChangedEvent != null)
                {
                    MaritalStatusChangedEvent(this,
                        new MaritalStatusChangedEventArgs("Marital Status is now " + _maritalStatus));
                }
            }

        }
    }

    public string GetFullName()
    {
        return string.Format("{0}, {1}", LastName, FirstName);
    }

    public override string ToString()
    {
        return string.Format("{0} {1}", FirstName, LastName);
    }
}

And let’s create a List of Person objects:

var people = new List<Person>()
    {new Person() {FirstName = "John", LastName = "Smith", DOB = "12/31/1968", IsMilitaryVeteran = true, MaritalStatus = 'M'},
     new Person() {FirstName = "Jimmy", LastName = "Crackcorn", DOB = "08/08/1934", IsMilitaryVeteran = true, MaritalStatus = 'S'},
     new Person() {FirstName = "Mary", LastName = "Contrary", DOB = "09/10/1957", IsMilitaryVeteran = false, MaritalStatus = 'D'}};

In a part 3 of this series on Lambda Expressions, we created a custom PersonCollection that inherited from List<Person> because we wanted to be able to filter these objects in specific ways. In that case, we were showing how to use a Lambda Expression with an Extension Method to loop through each Person that matched a certain Predicate<T> and perform some Action<T>. We initially did that by having the PersonCollection return another PersonCollection that was essentially a subset of the original. We could have also passed a more complex Lambda Expression that performed the filtering behavior for us as well as the Action.

In essence, though, the filtering done by the PersonCollection methods is a Query of the sequence. Rather than requiring a custom collection and predetermined methods, LINQ handles the query part for us. This buys us a couple of things. First, it means that we do not need a custom collection just to retrieve a filtered subset. Second, by not embedding this behavior in a Lambda Expression, we are substantively separating filtering behavior from actions on the filtered results. This means that both the filtering and the actions can be modularized.

Let’s look at an example:

var subset = from p in people
             where p.Age > 40
             select p;Console.WriteLine("Over 40:");

foreach (var person in subset)
{
    Console.WriteLine("{0} {1} is {2} years old. DOB: {3}", person.FirstName, person.LastName, person.Age, person.DOB);
}

If you compare these results to the list we created above, you’ll find that only the two over-40 objects are in the subset variable. This is what LINQ to Objects does for you: it allows you to query the Collection for a subset of objects. The resulting list is in fact an IEnumerable<T> for whatever type is in the Collection, so in this case we get back a list of Person objects. It also means I do not need access to the PersonCollection source code: I can execute LINQ statements over the collection directly, even if it is seaed, so I do not need to be able to create custom methods.

This is very powerful. Again, I’m not going to go over the mechanics of LINQ here, but suffice it to say that even this simple example should make you start to salivate. Imagine the possibilities! And it can be done with a very small amount of code.

Something more complex

As you may expect, the queries you write can be much more complex and functional:

var subset = from p in people
             where p.FirstName.StartsWith("J")
                && p.IsMilitaryVeteran
                && p.Age > 40
             select new {
                 LastName = p.LastName,
                 FirstName = p.FirstName,
                 Age = p.Age,
                 DOB = p.DOB
             };

There are some pretty cool things going on here that you need to be aware of. First, notice that I have complete access to all the members of the Person object in my query. Second, while a LINQ statement bears a strong resemblance to SQL, it is not SQL, so don’t judge it based on your SQL experience. Notably, it uses C# syntax and at first glance it appears backwards since the Select statement is last instead of first. This was done in order to support Intellisense, and Kathleen Dollard made a good point at a recent User group presentation: you may start to see SQL switch to this model (at least in the Microsoft World): wouldn’t it be nice to have full Intellisense support when writing SQL statements?

The third item of interest here is also in the Select statement. The first LINQ statement you saw returned an IEnumerable<Person>, but this one does not! In the select statement, we are actually creating an Anonymous Type by selecting only bits and pieces from our Person objects. In fact, these bits and pieces could come from multiple sources or be calculations or even new instances of complex types! This process of creating Anonymous Types from LINQ is known as Projection and it is very intriguing.

We discussed Anonymous Types and Compiler Inference in part 1 of this series, and now we see why they are so crucial. Without them, LINQ would be relegated to simply building subsets of Collections. With Projection though, LINQ becomes enormously powerful. Compiler Inference is used to create and build the Anonymous Type on the fly, and then is used again in order to loop through the newly created sequence. Without it, we would not be able to process the LINQ results, because in the case of projection there is no way to know the resulting Anonymous Type at design time.

Deferred Execution

I would be remiss if I did not at least point this out. A LINQ query is just a statement of execution: in other words, it is only a set of instructions concerning how to query a collection, it does not represent any data itself. No data is processed until the LINQ result object is referenced. This is called deferred execution, and you must be aware of it. If you do not understand this, “unpredictable results may occur”. Here is an example:

// Only define LINQ query - no data yet!
var subset = from p in people
             where p.FirstName.StartsWith("J")
                && p.IsMilitaryVeteran
                && p.Age > 40
             select new {
                 LastName = p.LastName,
                 FirstName = p.FirstName,
                 Age = p.Age,
                 DOB = p.DOB
             };
// "Subset" holds no data at this point

// Add new Person after LINQ query
people.Add(new Person() { FirstName = "Jill", LastName = "Upthehill", DOB = "12/31/1944", IsMilitaryVeteran = true, MaritalStatus = 'S' });Console.WriteLine("Over 40:");

// References LINQ query: NOW the data is gathered, so it includes the new Person
foreach (var person in subset)
{
    Console.WriteLine("{0} {1} is {2} years old. DOB: {3}", person.FirstName, person.LastName, person.Age, person.DOB);
}

Because the data itself is not read at LINQ definition time, it also means you can outsource the LINQ statements themselves to other classes and methods. Just be sure you return IEnumerable of Person:

public IEnumerable<Person> JVets(List<Person> people)
{
    var subset = from p in people
                 where p.FirstName.StartsWith("J")
                    && p.IsMilitaryVeteran
                    && p.Age > 40
                 select p;

    return subset;
}

Build your own Sequence

So far, we have been consuming known Sequences (such as List<Person>), but what if you wanted to perform LINQ over one of your own custom collection types? Hopefully by now the answer is obvious: you need to inherit from IEnumerable<T> or one of its children. The easiest way by far to do this is to inherit from one of the generic collections, such as List<T>. This would be my recommendation, but if you feel like getting into the nuts and bolts a little more, then you can implement IEnumerable<T> directly:

class PersonCollection : IEnumerable<Person>
{
    #region IEnumerable<Person> Members
    public IEnumerator<Person> GetEnumerator()
    {
        foreach (Person p in this)
        {
            yield return p;
        }
    }
#endregion

#region IEnumerable Members
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
#endregion
}

This is back to creating custom Iterators, which is beyond the scope of this article, but the magic here happens in yield return. This allows the collection to halt at each iteration and retain its position in the collection.

But here is the bad news: if you do this, you also have to implement all the Collection goodies, like Add(). This would be tedious and time consuming, and largely unnecessary since you could simply inherit from one of the Generic classes.

Conclusion

As stated at the beginning, this is not meant to be a LINQ primer. What you should get out of this is the following: you should use LINQ whenever you want to query collections. You can use LINQ to create collections of anonymous types, limiting the data and properties you have to deal with to just the ones you want. You can use LINQ to logically separate your queries from your actions.

And there is much more you can do with LINQ. You can aggregate results, join collections together, and so much more. Try it the next time you need to loop through a colleciton and pull out just certain objects. I think if you use it a couple of times you’ll find it becomes useful in a hurry.

Categories: .NET 3.5, C# 3.0, LINQ

Live Blogging RVNUG – December 2007

December 6, 2007 Comments off

Tonight I am visiting RVNUG (Roanoke Valley Dot Net Users Group) for the first time. Kathleen Dollard, a columnist for Visual Studio Magazine and author of Code Generation in Microsoft .NET (which I have and have read most of) is the featured presenter. She will be discussing “Refactoring with Generics”. How to make your code better with Generics, using Framework Generics, and how to use and make your own Generics.

Here are some bullets I garnered from the presentation:

  • Find out about the Converter<T> Generic Delegate.
  • “Team Test” is now part of VS2008.
  • Anonymous Delegates employ “Closure” – allows a private variable to be trucked off to (captured by) an out of scope method (like an anonymous delegate)
  • Return a LINQ list immediately by using “.ToList()”: no deferred execution
  • Format for declaring my own generics and specifying Type inheritance: public class GenericClass<TData, TCollection> : SomeBase where TCollection : List<TData> where TData : class

Conclusions

Overall, a good presentation. Unfortunately, it is a little dated when you consider all the new technologies out there. Kathleen did include some optional approaches using LINQ and Lambdas, but the bulk of the material is still 2.0 based. Don’t get me wrong: I’m not saying I didn’t learn anything because I did. I think I have a much better handle on creating my own generic classes now. But I think the target audience for this presentation should be developers moving from 1.1 to 2.0 or new developers.

Now for the scary part: the topic is very relevant. There are still an incredible number of people developing in pre-2.0 technologies who need this kind of information.

Kathleen is great: if you ever get a chance to go to a presentation of hers, by all means treat yourself: she really knows her stuff. We had a nice talk during dinner about the future of LINQ to SQL, OR/M, the Entity Data Model, and other Framework issues.? She was very patient with my questions and her answers reveal that she is one smart cookie.

Categories: .NET 3.5, C# 3.0