Archive for October, 2005

Rubyish collections in C# 2.0

Tuesday, October 11th, 2005

In the limited amount of time that I have played around with Ruby, I have been impressed with how easy it makes a lot of things. Utilizing the power of blocks, it is this simple to print out the contents of an array.

    list.each {|item| puts item}

C# 2.0 gives you something similar to blocks with the new anonymous methods. Say you want to show a message when a button is clicked. Before 2.0 you had to do quite a bit of coding to implement the feature.

First, you have to implement your method.

    private void button1_click(object sender, EventArgs e)
    {
        MessageBox.ShowMessage("Hello, World!");
    }

Then you have to assign the method to the click event.

   button1.Click +=  new System.EventHandler(button1_click);

With anonymous methods, this task becomes much simpler.

    button1.Click += delegate { MessageBox.Show("Hello, World!"); };

Granted, if you had a decent designer, most of this would be done automatically, but you can still see how much easier stuff like this is in C# 2.0.

After looking at the examples for anonymous methods, it got me thinking about whether you could implement methods on a list class similar to the way Ruby does. So I started by making a delegate method, and a descendent of ArrayList.

    delegate void EachDelegate(Object item);

    class MyCoolList: ArrayList
    {
        public void Each(EachDelegate delegateMethod)
        {
            foreach (object obj in this)
                delegateMethod(obj);
        }
    }

Now, to print out the contents to the command line.

    MyCoolList list = new MyCoolList();
    list.Add("foo");
    list.Add("bar");
    list.Add("baz");
    list.Each((EachDelegate)delegate(object obj) { Console.WriteLine(obj.ToString()); });

The syntax is a little ugly, but at least all of the code is there in the same method. Now that I have a class that implements each, lets look at leveraging generics to make the class, well more generic.

First we need to make our delegate generic.

    public delegate void EachDelegate<ReallyCoolListElement>(ReallyCoolListElement element);

Then we make our list class descend from List<T> and use the new generic delegate in our Each method.

    class MyReallyCoolList<ReallyCoolListElement> : List<ReallyCoolListElement>
    {
        public void Each(EachDelegate<ReallyCoolListElement> delegateMethod)
        {
            foreach (ReallyCoolListElement obj in this)
                delegateMethod(obj);
        }
    }

To use this new class we can modify the original code to look like this.

    MyRealyCoolList<string> list = new MyReallyCoolList<string>();
    list.Add("foo");
    list.Add("bar");
    list.Add("baz");
    list.Each((EachDelegate<string>)delegate(string element) { Console.WriteLine(element); });

Or if you wanted to use it to sum up a list of ints.

    int sum = 0;
    MyRealyCoolList<int> list = new MyReallyCoolList<int>();
    list.Add(1);
    list.Add(2);
    list.Add(3);
    list.Each((EachDelegate<int>)delegate(int element) { sum += element; });

The syntax in C# is not nearly as nice and sugary as Ruby, but this does demonstrate some of the cool new features that are being added to C# 2.0.

Nano goodness

Wednesday, October 5th, 2005

I have to admit that Apple is really good at innovation and creating gadgets that just beg to be purchased. I have been able to resist them for the most part, but when the Nano came out, it was just to hard to restrain myself. The Nano was definitely worth the money, and it’s size is just awesome. The only drawback is its susceptibility to scratching. The front still looks great and you can only see the scratches if you are really looking for them. However, the scratches on the back are quite noticeable. Hopefully Apple will fix this with future Nano versions.

Installation Alternative?

Wednesday, October 5th, 2005

At work, we are using Wise as our installation solution. However, I have been very unhappy with the quality of their software. Many times when trying to get something to work in Wise, it comes to the point where you ask the question,”What is the stupidest thing that I could do to get this to work.” Usually the answer to that question is what we have ended up doing to get the features that we want. Sam and I have thought about trying to roll our own Delphi application to do the installation, but there are some features of Windows Installer that we would miss without a lot of extra work.

Anyway, enough of that rant. I was looking at an issue with Svn1ClickSetup where it was not installing TortoiseSVN into the correct directory, and I was trying to find out if I was using the wrong MSI property to set the install directory (that was the case BTW). So I started poking around the Tortoise source code, trying to find their installation code. I finally found some files that looked promising, but they had the extension .wxs, which I was not familiar with. Viewing the files, they looked like some sort of XML way to specify an installation. Interesting. So after some googling, I found this site. WiX is a toolset that Microsoft has released (open-source, no less) to allow you to describe your MSI using XML. There is also a Visual Studio plug-in for developing WiX scripts.

I don’t know how easy it is to create an installation using WiX, especially for an installation as complex as ours, but it looks like it could be a possible replacement for Wise. Since it uses XML to describe the installation, there is always the possibility of writing an application to generate the code. Definitely something that bears some more research.