OdeToCode IC Logo

More Fun With Generics: Action, Converter, Comparison

Sunday, July 11, 2004 by scott
As a follow up to yesterday’s blog about the Predicate<T> delegate, I wanted to try out the three additional delegate types in the generics area.

First, a new type to work with:

class Person
{
   public Person(string name, DateTime birthday)
   {
       this.name = name;
       this.birthday = birthday;
   }
 
   public string Name
   {
       get { return this.name; }
       set { this.name = value; }
   }
 
   public DateTime Birthday
   {
       get { return this.birthday; }
       set { this.birthday = value; }
   }
 
   string name;
   DateTime birthday;
}

The Comparison<T> delegate represents a method used to compare two types. If you have ever needed to define an entirely new type deriving from IComparer just to tell Array.Sort how to compare two objects, you’ll appreciate the brevity in the following sample.

List<Person> list = new List<Person>();
 
list.Add(new Person("Alex", DateTime.Now.AddYears(-30)));
list.Add(new Person("Neal", DateTime.Now.AddYears(-20)));
list.Add(new Person("Geddy", DateTime.Now.AddYears(-25)));
 
list.Sort(
      delegate(Person x, Person y)
      {
        return Comparer<DateTime>.Default.Compare(x.Birthday, y.Birthday);
      }
 );

Next is the Converter<T,U> delegate. Use this delegate to convert each object of type T in a collection to type U.

List<int> yearList;
yearList = list.ConvertAll<int>(
        delegate(Person p)
        {  
            return p.Birthday.Year;
        }
   );

Finally, there is the Action<T> delegate. Use this delegate to perform an action with each object of the collection.

yearList.ForEach(
        delegate(int year) { Console.WriteLine(year); }
    );

I am generally grouchy about any new language feature until I can write some code and figure out its purpose in life. Generics I knew would be a hit, and after writing this code I’m starting to warm up to anonymous delegates.

Generics and Predicates

Saturday, July 10, 2004 by scott
What will be an elegant technique to remove objects matching a condition from a List in C# 2.0?

If the following code finds a match, we’ll find out it’s a no-no.

foreach (string s in list)
{
    if (s == "two")
        list.Remove(s);
}

In VS2005, the code creates this friendly little dialog.

C# 2.0 introduces generics, and with generics come predicates. A predicate returns true when an object meets a set of conditions, otherwise false. A method like List.RemoveAll will run each object in the collection through a given predicate to test each object for a match. When the predicate returns true, the method removes the object from the collection. The nifty thing is, you can write the predicate as an anonymous delegate:

list.RemoveAll(
    delegate(string s)  { return s == "Two"; }
);
 

Alternatively, you can keep your logic inside a named method.

static bool MatchTwoPredicate(string s)
{
    if (s == "Two")
        return true;
    return false;
}

// and later . . . 
 
list.RemoveAll(MatchTwoPredicate);

I feel either technique is easier on the eyes when compared to STL and functors in C++. Then again, I should be sleeping right now instead of blogging.

Does Michael Powell Have The Ugliest Blog On the Planet?

Saturday, July 10, 2004 by scott

While veering through Yahoo news this evening I came across the headline: “FCC Boss Launches Blog Aimed at High-Tech Industry”.

I was stunned.

For the first time ever I read about a new blog from a source outside the blog world. Usually you find out about these sorts of thing by plowing through 25 insightful blog entries which read: “so and so is blogging – subscribed!”.

In true Yahoo / Reuters fashion, however, the news article didn’t contain an actual link to the blog, but links to news and websites about the FCC. At the very bottom of the article, they put in the URL, but not in a hyperlink. I cut and pasted the URL into IE.

I was stunned.

I really thought I had reached the wrong server. I see a big broken banner on the top because ActiveX controls are disabled for the Internet zone. Advertisements and menus appear randomly on the page, and there is a huge gap of whitespace to scroll through before blog entries appear.

[update: i've been informed this is because I also have JavaScript disabled in the Internet zone. DUH! Ah, the pleasures of running Win 2003 Server and hardened security on a desktop machine. Still - the colors give me a headache.]

Then I reached the bottom of the page, which included more advertisements from Sun, IBM, and AOL. On a hunch, I viewed the page in Firefox. Suddenly, the layout improved. Menus aligned. Caverns of white space turned into proper half inch borders.

The colors still give me a headache, but it’s hard to cram 22 advertisements on a page without looking like a dryer full of checkered golf clothes.

Interesting that the head cheese of the FCC has a blog that doesn’t render well in the most popular browser on the planet. [update: ok, maybe it does render with everything enabled, but it's still UGLY!]

Latest OdeToCode Articles

Thursday, July 8, 2004 by scott

ASP.NET 2.0 and Site Maps

Thursday, July 8, 2004 by scott
I hereby interrupt the “week of the malcontent” with the “evening of possible enlightenment”.

The provider design pattern in ASP.NET 2.0 is sweet. I’ve been toying around in the SiteMapProvider area since the first CTP. There is an XmlSiteMapProvider which let’s you describe the navigation and layout of your web site in an XML file like so:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
  <siteMapNode title="Home" url="Default.aspx" >
    <siteMapNode title="Products" url="Products.aspx">
      <siteMapNode title="Seafood" url="Seafood.aspx"/>
      <siteMapNode title="Produce" url="Produce.aspx"/>
    </siteMapNode>
    <siteMapNode title="Contact" url="Contact.aspx">
      <siteMapNode title="Email Us" url="Email.aspx"/>
      <siteMapNode title="Phone List" url="Phones.aspx" />
    </siteMapNode>
  </siteMapNode>
</siteMap>

Without writing a line of code (just some drag and drop operations), you can give all the pages in your site a tree view of the site hierarchy and a bread crumb control:

What if your site navigation comes from a database table?

NodeID URL           Name     ParentNodeID 
------ ------------- -------- ------------ 
1      Default.aspx  Home     0
2      Products.aspx Products 1
3      Seafood.aspx  Seafood  2
4      Produce.aspx  Produce  2
5      Contact.aspx  Contact  1
6      Email.aspx    Email    5
7      Phones.aspx   Phone    5

All you need to do is derive from the abstract class SiteMapProvider and override a handful of methods, like GetParentNode and GetChildNodes. These methods can be straightforward to implement with a few pre-built collections of type Dictionary<string, SiteMapNode>. SiteMapNode objects represent the nodes in the site map, while a Dictionary is one of the exciting new classes from the System.Collections.Generic namespace, which you can use to build strongly typed collections.

One you have some code querying SQL Server and implementing the SiteMapProvider methods, you just need to tell the runtime about your new provider via a config file:

<siteMap defaultProvider="MySqlSiteMapProvider" enabled="true"> 
  <providers> 
    <add name="MySqlSiteMapProvider" type="SqlSiteMapProvider"
         connectionStringKey="ConnectionString"/> 
  </providers> 
</siteMap> 

You can have multiple providers for a site. If half of the site navigation information comes from XML and the other half from the database, that’s quite possible. It will be interesting to see what other providers come out. I'm sure SQL, and File System providers will be in demand.

Why Do Microsoft Webcasts Have To Stream?

Wednesday, July 7, 2004 by scott
The MSDN Webcasts Weblog is online. Since I am doing nothing but whiney posts this week, then I’d like to ask: Why can’t we download the webcasts for offline viewing?

Bill has me salivating over the Personal Media Center. I started to imagine myself downloading MSDN TV, Channel 9 videos, and TechEd webcasts to watch at my leisure, away from the desktop. There are just two problems with this dream:  

  1. The Personal Media Center isn’t for sale as yet.
  2. The Microsoft webcasts do not download as a file I can save, they only stream.

[Updated with MSDN Webcasts new URL].

Yearning for Yukon

Tuesday, July 6, 2004 by scott
Let me say that the Express version of SQL 2005 has not been a disappointment to me.

The disappointment has been in not getting a new beta of the ‘real thing’, the ‘Venti espresso’, the ‘yellow yolk of the Yukon egg’.

I have not tried to do much with SQL Express. As soon as I heard the product mentioned in the same sentence as MSDE, I pictured it appearing in the Server Explorer window of the IDE, doing all the mundane things databases have done for the last 5 years. I think a previous forced experience in wrestling with MSDE helped me figure out some of the quirks, like hunting down the instance name to make a connection [use (local)\SQLEXPRESS].

I did come across an interesting error message. I was curious to see if SQL Express, like MSDE, defaults to Windows Authentication only (and it does). In toying around, I tried to “sp_addlogin ‘user’, ‘user’” (just as a test, you see, to set the password the same as the username), and had the following thrown back at me:

 
Password validation failed. The password does not meet policy
requirements because it is not complex enough. 

Interesting.

Also interesting: I came across a SQL Express rant and a MySql success story in back to back posts this evening. I hope something gets released before the trend continues.

UPDATE: One more SQL Express rant, and a SQL Express success.