IEnumerable ForEach extension method

List<T> has a method called ForEach that takes an Action<T> delegate, and I wanted one for IEnumerable. I also had someone ask about it in my previous post. It wasn't hard to write, but I figured I would throw it up here for future reference and also in case anyone needed help getting theirs working. If anyone notices anything I did that was dumb you can give me feedback as well. I believe I actually implemented something similar to this a while back, but anyways... without further ado...

public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    if (enumerable == null)
        throw new ArgumentNullException("enumerable");
 
    if (action == null)
        throw new ArgumentNullException("action");
 
    foreach (T item in enumerable)
    {
        action(item);
    }
}

Hope it helps.

The Linq SelectMany Operator

Most of you by now are familiar with LINQ, Microsoft's foray into crossing the code/data impedance mismatch. Most of what we see in Linq translates directly into our knowledge of SQL, since most LINQ queries use very similar semantics to SQL queries. There are certain operators though that don't look familiar because they either weren't present in our SQL lexicon or they were represented in a fundamentally different way. A little bit back I posted about one of these operators, the "let" operator, and how to use it effectively. I later followed it up with a post that dug a little bit deeper into the "let" operator so that you could get a peek at what was going on behind the scenes.

Today I introduce to you another one of these operators that is even a bit more foreign to those coming from a SQL background, it is the SelectMany operator. This operator doesn't have an explicit native syntax when dealing with LINQ queries, so we will first go over the operator using the LINQ extension methods and then we will show you how to achieve the same effect using the native C# LINQ syntax. Sound good? Good.

The SelectMany operator is described on MSDN as "Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence." Well, that is actually a pretty good description, but until you see it work, it is hard to visualize it. Well, at least it was for me!

In order to first give an example of this operator we will start off with the same list of names that I used in my previous post about the "let" operator and we will select the list with both the "Select" and the SelectMany operator to see what happens.

var nameList = new List<string>
                   {
                       "Matt",
                       "Adam",
                       "John",
                       "Peter",
                       "Owen",
                       "Steve",
                       "Richard",
                       "Chris"
                   };
 
var names1 = nameList.Where(n => n.Length == 4)
    .Select(n => n).ToList();
 
names1.ForEach(n => Console.WriteLine(n));
 
var names2 = nameList.Where(n => n.Length == 4)
    .SelectMany(n => n).ToList();                            
 
names2.ForEach(n => Console.WriteLine(n));

So, here you see the same two queries with only the Select and SelectMany swapped out. Then we write the results out to the console, so, what happens when this is executed (with a bit extra formatting code)?

image

What just happened there? The Select just returned the list of names that we filtered out. In fact, the select is entirely unneeded. If we left it off, then the query would execute identically, I only put it in there so you can see the difference. The SelectMany on the other hand got the list of names with four letters and since String is an IEnumable<Char> it then projects each String as an IEnumerable and then combines the results. So, as you can see, we got a single result with each character of each name in our list.

But how is this useful to us? Actually there are quite a few wonderful uses for this. Lets look at what we could do if we changed our example above to have several lists of names instead of just one.

var nameList = new List<List<string>>()
                   {
                       new List<string>
                           {
                               "Matt",
                               "Adam",
                               "John",
                               "Peter",
                               "Owen",
                               "Steve",
                               "Richard",
                               "Chris"
                           },
                       new List<string>
                           {
                               "Tim",
                               "Jim",
                               "Andy",
                               "Fred",
                               "Todd",
                               "Rob",
                               "Richard",
                               "Ted"
                           }
                   };           

You can now see that we have two different lists of names and how do we get the list of names with only four characters now? Without using SelectMany we could do this:

var names1 = nameList.Select(l => l.Where(n => n.Length == 4));
foreach (var list in names1)
{
    foreach (string name in list)
    {
        Console.WriteLine(name);
    }
}

Hmmm. You see where we are doing a sub query to select the names from each list. We then have a nested IEnumerable<IEnumerable<string>> that we have to use nested loops in order to access our names. But with SelectMany we should be able to select our names from our list and avoid the nested IEnumerable.

var names2 = nameList.SelectMany(n => n)
    .Where(n => n.Length == 4)
    .Select(n => n).ToList();
 
names2.ForEach(n => Console.WriteLine(n));

Pretty easy! Here we are actually using the SelectMany operator first in order to flatten the lists and then we are filtering it using a Where statement. Again, the Select here is not required, but I have thrown it in to be more explicit. What I am doing above though may hide a little bit of what is happening. In order to better show that you are actually passing an IEnumerable into SelectMany I am going to show you an example where we are splitting up a few sentences about the people in our list above. What we are going to do is to have a list of sentences, and then split those sentences into words.

var sentences = new List<string> {"Bob is quite excited.", "Jim is very upset."};

This is our list of sentences, and now we need to get our individual words out of this:

var words = sentences.SelectMany(w => w.TrimEnd('.').Split(' ')).ToList();

Here we do a SelectMany on our list of strings, and then we are removing the period from the end of the sentence, and then we split them on a space and the result of the call to "Split" is what SelectMany then operates on. If we took the Split off then it would simply treat each item as a String and then we would end up enumerating over each character like we did in our first example.

I hope that this has cleared up the SelectMany operator for you, and so now we have just one last thing to do which is to show you how to do a SelectMany using the native C# LINQ syntax. But, how do you do a SelectMany if there is no native query operator for it? Well, you do it by chaining from statements. That may sound weird, but check it out, it actually works quite well.

var words = from s in sentences
            from w in s.TrimEnd('.').Split(' ')
            select w;

See? You are simply funneling the first "from" into the second "from". The reason why this works so well is that it lets you nest even further very easily. For example, what if we wanted each individual character from the above query.

var characters = from s in sentences
                from w in s.TrimEnd('.').Split(' ')
                from c in w
                select c;

Now all we did was split the words, and then select each character out of our list of words. Pretty sweet, and it can allow you to drill down into multiple levels of data very very easily. To me it also gives a good visual flow as to what is happening, but you don't get any indication that a new operator is being involved.

Well, I hope this helps clear things up a bit, and I hope that you get some good use out of this!

When technology attacks

burning_harddrive

I am sitting here writing this blog post on my fresh new Vista x64 SP1 install, which was a debacle that took only 2 days to complete. I know you probably do not wish to be regaled with yet another tale of Vista install issues, but this is one that does an excellent job of construing the complexity that is modern technology and showing you that the old adage "the simplest explanation is the correct one" may not always be correct.

It all started a few months back when I purchased a new Dell M1530 laptop. I bought it with a tiny 5200rpm drive and 1GB of ram (which actually isn't even an option anymore) and I installed a nice 200GB 7200rpm drive (with a 16MB cache) and 4GB of RAM. By the way, before you start screaming "Mr. Moneybags" the RAM was about 80 bucks and the harddrive was about 170 dollars. This stuff is so cheap these days it is embarrassing. I loved the laptop, it is quite fast (and I have had several people comment on how fast it is), but I always had one problem... the freakin' thing ran as hot as the fires of Hades. The shell on it is all metal though, so I thought it was just acting like a giant heatsink. The key word here being "thought".

Everything ran fine though, I had no other complaints or problems at all. So, yesterday Vista SP1 finally popped up on my Windows Updates list and so I decided to install. The install started running and went through its usually paces until it restarted and drops to a black screen where it starts copying files. The files were counting up higher and higher until I suddenly get an error that looked something like "!! 0x00000c2 !!" with the name of the file that it stopped on "ExplorerFrame.dll". Great, I thought, SP1 hosed my system. I tried to reboot and it started through the process again, but it locked up again. By this time, with all of the file copying and hard drive activity my laptop was getting quite hot. I decided to go online and see if I could find anyone else having this issue. Well, I found quite a few people that were experiencing this problem. But the only solution was to do a restore back to the restore point that Vista SP1 creates.

So, I restarted my machine and went into the BIOS to configure it to boot from the DVD drive, and my laptop suddenly shut off. What? I rebooted and went back to the BIOS, this time successfully and then I popped in the Vista x64 DVD, booted up the computer and it started loading. But as soon as it finished loading and was supposed to pop into the Vista repair screen, my laptop turned off. What?

Yep, it just powered down. So I hit the power button to turn it back on and popped in the DVD and the same thing happened again. By this time though, the laptop was getting extremely hot. Why was it getting so hot? It wasn't any more hot than I had ever felt before, but I thought that maybe inside Windows there is more cooling management features that run to keep the CPU from running too hot? (I don't know, is there?) So, I decided to give my laptop a rest.

I let it rest for about an hour and I came back and booted the restore DVD and it worked. I got to the restore prompt, began running the restore and it locked up about 10 minutes into it. I let it run for about 30 minutes and suddenly the laptop cut off. How was I going to get my laptop restored? And these shutoffs looked exactly like it was an overheating issue, but I had never had any problems before. Well, I decided to go ahead and go the nuclear route first, and just restore from my backups (yes, I run Acronis TrueImage regularly. I am a paranoid person and it has *always* paid off). But I bet you can guess what happened next. First I had to install the latest version of TrueImage on another machine, since my laptop was the only one running version 11, so that I could create the restore media. Then I had to burn a cd and boot from it on my laptop. I completed this cycle only to have my laptop cut off on me right in the middle of my restore.

Okay, so now I had a totally hosed hard drive since it was half restored. I was now starting to worry a bit, but I decided that my laptop was just getting too freaking hot and it didn't look to me like the fan was coming on at all. So I went ahead and flipped my laptop over and do some surgery. (If you are from Dell, you can stop reading now) I popped off the cover where the RAM is, since that also exposes the CPU, Graphics card, and heatsink fan. I followed the wire from the heatsink and it went down the side of the fan casing and followed a copper tube that went from the CPU over to the GPU (or it could be the motherboard chipset). There were three different chips that this copped tube went over.

I followed the wires and I couldn't really see where they went, but then I saw what looked like a tiny fan connector with nothing plugged into it. I poked around under the copper tube and out popped a fan connected. Wow. The fan on my CPU had never been plugged in. I guess that is a testament to the heat management that is put into laptops these days, but I was a bit pissed off, because I'm sure that this has now shortened the life of my laptop. The only thing I can guess is that while running in windows that the CPU is slowed down or something to compensate for the heat. Not to mention the fact that I rarely use my laptop for periods of longer than a few hours. But I had seriously been running this thing with absolutely no active cooling for several months now, unbelievable.

I plugged the fan in and turned my laptop back on. I started up the Acronis recovery (which took about an hour) and halfway through the difference was stark. My laptop had been doing continuous file copying and processing for 30 minutes and it was barely warm (I could also now hear the very low hum of the fan). Well, I completed my restore, and I thought that maybe the Vista SP1 upgrade had failed because the laptop had overheated, so I decided to go ahead and run it again. I did a full backup first though, just to be safe.

Of course that wasn't my problem, it locked up again. So I went ahead and recovered my hard drive again. What was I going to do? I am not going to have Vista reminding me every 4 hours that I have updates which I am unable to install. That would drive me insane. But at the same time I don't want to set the updates to be ignored, because after a service pack is released I believe that updates for pre service pack installs stop. Not to mention that there are some important updates in SP1 that I want!

My next thought was that maybe something was screwed up on my hard drive. I had after all been running my laptop for several months under conditions that simulated the bottom of an active volcano. It wasn't out of the realm of reality that my hard drive had begun to fail. So I ran chkdsk and amazingly it found an error in the NTFS indexes on the exact file that my SP1 install was locking up on! So, I ran "chkdsk /F",  rebooted and let it try to fix all my problems.

I then rebooted one last time into Windows, crossed my fingers, and ran the SP1 update one last time. And, as we both know, it succeeded. Otherwise you would not be getting this post right now and my wife would be getting a migraine. So, let this be a lesson to all those out there, before you start blaming Vista, OS-X, Linux, or whatever for your problems...it may not be quite that simple.

Oh, and Microsoft, why don't you just force a chkdsk run *before* you install a service pack? The SP already takes forever to install, what is an additional 20 minutes?