More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  DevelopmentalProfileFriendsBlogMore Tools Explore the Spaces community

Developmental

Flinging crap at other monkeys in the development forest
August 29

DEVSTA - The programming competition for star developers!

Although it hasn't been officially announced by Microsoft yet, the information was revealed on the OzSilverLight mailing list today that there will be a programming competition for Australian developers starting in September.

Here is the URL: http://devsta.microsoft.com.au/

What's really interesting about this particular competition is that it is offering some seriously cool prizes! For instance, first place is an all expenses paid trip to Mix09 in Vegas next year, an XBOX Elite plus games, and a MSDN subscription.

The "theme" of the competition will be announced on 29th September, and then it will be open slather. Developers will have exactly 200 hours and 8 minutes to complete their submission for the competition.

So start stocking that jolt cola and be ready on 29th Sept to compete to become the next DEVSTA!

August 20

System.IConvertible - Its not a Ferrari

You might be familiar with the System.Convert class, which has a number of methods for converting from/to different types. For example:

short s = Convert.ToInt16(int.MaxValue);

We live in a world of casting and you might find this code somewhat pointless. After all, it will still raise StackOverflowException and lose precision with floating poing conversions, so what's the point?

The convert class is capable of converting an instance of ANY type into one of the common base types (sting, int, ulong, char, etc). If a type implements the System.IConvertible interface, it can define how conversions of that type will occur.

Lets consider a (not so practical) example. Say we have a product class with the following properties:

public int ProductId { get; set; }
public DateTime DateAvailable { get; set; }
public string Name { get; set; }

Our Product class also has a parameterless constructor. In this example, we also make the Product class implement the IConvertible interface. This forces us to implement 16 methods and 1 property. Those methods all relate directly to conversion. For example, here's the implementation of one of those methods:

public ulong ToUInt64(IFormatProvider provider) {
      return (UInt64)ProductId;
}

What we are saying here is that if someone tries to convert our Product instance to a ulong then it will simply assign the ProductId. Our test code looks like this:

Product p = new Product { Name="Car", DateAvailable=DateTime.Now, ProductId=7 };
UInt64 i = Convert.ToUInt64(p);
Console.WriteLine(i);

The output is the number "7" because that is how our implementation of IConvertible tells the Convert class to handle conversions to UInt64.

Simple eh?

 

July 01

Rolling back a changeset in TFS

In TFS 2005 and 2008 there is no easy way of rolling back a changeset. Sure, you can do a "get specific version" of each file from before the "bad" checkin occurred, and then check the older version back in. But this really sucks if you have a lot of files in your changeset.

Luckily the Team Foundation Power Tools can help you here. One of the command line options is as follows:

tfpt rollback /changeset:xxxx

Here, you simply replace xxxx with your changeset number, and the power tools will take care of the rest.

First, it will "get latest" of the workspace. Next it will perform an operation for each file that is required to roll it back. For example, if you added a file, it performs a delete. If you deleted a file, it performs an undelete. If you simply edited a file, it will get the code from the changeset previous for that file. The result on the command line indicates which changeset was used for each file it rolled back.

It then pops up a window requesting confirmation for all the files. After this, it checks out all those files it will roll back and you can then check them in (or only check some in if you so wish).

One caveat with this process is that when you are executing the command line, you might get an error: "Unable to determine workspace". This simply means you are not currently in a folder that is part of a workspace. Change directory into a folder that is stored in the workspace you want to use (for those that use multiple workspaces with different folders).

Good news is that Rosario will have rollback features incorporated. Check out the help for rollback for more information:

tfpt rollback /?

Technorati Tags: ,,,,
June 13

Destroy Work Item : Is it really gone?

This week we had a situation where we needed to remove a work item from the TFS database completely. You can delete a work item in Team Explorer however this just marks the row in the database as deleted and as such your database will always grow, never shrink.

The Visual Studio Team System 2008 Team Foundation Power Tools give us the ability to destroy a work item with the 'destroyWI' call. Here's the command line syntax:

tfpt destroywi /server:<SERVER> /workitemid:<ID>

The 'intention' is to delete all instances of the ID from the database, and all related data, and in truth it comes pretty close. However there is one table it misses: 'WorkItemsWere'

If you look at your TFS database instance you will notice there are actually a few databases. One of them is 'WorkItemTracking' and this database contains all the tables related to work items. The astute might also notice that each of the databases in their instance seems to match each of the web services provided by TFS. Coincidence?

In the 'WorkItemTracking' database you will see a number of tables that all contain work item related data. In particular, notice the two tables: 'WorkItemsAre' and 'WorkItemsWere'. The 'Are' table contains the current state of a work item while the 'Were' table contains its history.

For example, work item 1234 is modified several times. First it is opened as a bug and assigned to 'triage'. Then triage moves it to the developer who fixes the bug and resolves it with comments, where it is assigned back to the user who opened it. The bug isn't fixed, some additional comments are inserted, its assigned back to the developer, and so on. If you are familiar with work items, you will be able to identify the 'History' section where you can view the audit history. This essentially is what is stored in the 'WorkItemsWere' table. Makes sense now right?

Yesterday I did a destroy of a work item and discovered that all the various tables had all instances cleaned up, except the 'WorkItemsWere' table. I contacted the VSTS team who indicated that this is indeed a bug and it is now logged in their own work item system (oh the irony!).

What to do in the mean time? Well they assure me it is safe to delete the orphaned database rows, despite the general consensus on the net not to mess with the database directly. I can confirm however that this is the only table with orphaned data. And I'm sure this will be fixed up in a future release of the power tools. All round I quite like the TFPT and haven't even bothered with the multitude of 3rd party components that put a UI in front of it: real men use command line!

June 01

Advanced Generics

I've recently been reading this book by Jon Skeet about C# 2 and 3, and it got me all inspired to write about generics. Jon's great; he's extremely active in the C# and Java community, and recently responded to an email question I had in less than 10 minutes! I'm finding the book insightful and useful and greatly enjoying my bus rides to work when I get to read it.

This post is going to assume you are familiar with using generic classes like List<T> and Nullable<T>. So lets start with the syntax for declaring our own generic class:

public class Monkey { }
public class Animator<T> {
    private T instance;
    public Animator(T t)
    {
        instance = t;
    }
    public void MoveOnce() { }
}
Animator<Monkey> animator = new Animator<Monkey>(new Monkey());
animator.Move();

This is pretty simple: the Animator class accepts a generic type T and requires you pass a T in its constructor. The MoveOnce() method is empty at the moment, we'll get to that later.

Currently our generic Animator class is somewhat type-safe: we can only pass instances of T to its constructor, but we don't really know much about T. We'd like to be able to move our instances (such as a monkey) so we need to define some things about what kinds of T we are willing to accept. Lets go back to our Monkey class for a moment and define an interface for it:

public interface IMoveable {
    void Move();
    void Stop();
}
public class Monkey : IMoveable {
    public void Move() { }
    public void Stop() { }
}

Great! We've decided that the fact a Monkey can move and stop is pretty general, and is probably something other animals can do, so we've declared an interface to indicate our monkey has those capabilities. We might also define IEater, or IDungFlinger. Now we can revisit our generic type in our Animator class definition as follows:

public class Animator<T> where T : IMoveable
{
    private T instance;
    public Animator(T t)
    {
        instance = t;
    }
    public void MoveOnce() {
        instance.Move();
        instance.Stop();
    }
}

This is where the magic begins. We've placed a constraint on our generic type, stating that it will only ever accept a type that implements our IMoveable interface. If we try to use the Animator class with something else, we will get a compile-time exception. Even better yet is that our development environment knows that since our instance will always implement IMoveable, it therefore must have a Move() and Stop() method, therefore we can call it anywhere in our class; in this case the MoveOnce() method.

You can declare more than one generic type in your class definitions. Imaging a class that facilitates a race for monkeys, whether they be chimps, gorillas, or marmosets. Consider this generic class declaration:

public class Race<T, U> where T : Monkey where U : Monkey {
    public Race(T monkey1, U monkey2) { }
    public void RunRace() { }
}
public class Marmoset : Monkey { }
public class Chimp : Monkey { }

Here we have defined that our class accepts 2 generic types: T and U. We have further restricted them that they both have to inherit from the Monkey class. Here's some example calls using this new class:

Race<Chimp, Marmoset> race1 =
      new Race<Chimp, Marmoset>(new Chimp(), new Marmoset());
Race<Monkey, Chimp> race2 =
      new Race<Monkey, Chimp>(new Monkey(), new Chimp());
Race<Marmoset, Marmoset> race3 =
      new Race<Marmoset, Marmoset>(new Marmoset(), new Marmoset());

As you can see that anything that inherits Monkey is valid. Of interest, the second example shows that even an instance of Monkey is valid. This shows that the where clause in our type restriction means anything that inherits from X or is X.

Finally here are a couple of extra cool things you can do with generic type restrictions as general non-monkey related examples:

public class TestCase1<T> where T : class { }
public class TestCase2<T> where T : struct { }
public class TestCase3<T> where T : IDisposable, IMoveable, IComparable { }
public class TestCase4<T, U> where T : U { }
public class TestCase5<T, U> where T : U, IMoveable { }
public class TestCase6<T, U> where T : class where U : struct{ }
public class TestCase7<T, U> where T : class where U : struct, T { }

TestCase1 demonstrates that we can force the type to be a reference type.
Likewise TestCase2 ensures that the type must be a value type. How is this useful? Well consider a generic class that performs expensive operations such as copying from one list to another. Reference types are just pointers and therefore inexpensive to copy around, thus ensuring only reference types are allowed in our class could be quite useful.

TestCase3 shows that we can ensure T implements multiple interfaces.
TestCase4 shows that one generic type can be forced to inherit from another. An example of an implementation might be:

TestCase4<Chimp, Monkey> test = new TestCase4<Chimp, Monkey>();

This is valid because Chimp inherits from Monkey.
TestCase5 shows that a type can be restricted to inherit as well as implement interfaces.
TestCase6 demonstrates that one type must be a reference type while the other can be a value type.

The last TestCase7 is somewhat interesting. Its declaration indicates that T is a reference type, and U is a value type that must inherit from T. How can this be? It essentially states that you must pass a struct that inherits from a class. But C# won't let you declare this.

To be honest at first I didn't know the answer to this. Thus the email to Jon, and his explanation was simple and it made sense: interfaces are reference types. Hopefully you are aware that structs can implement interfaces also (but can't do inheritance), so we might define a new animal as follows:

public struct Mouse : IMoveable {
    public void Move() { }
    public void Stop() { }
}

Then we can legitimately use the TestCase7 syntax:

TestCase7<IMoveable, Mouse> test = new TestCase7<IMoveable, Mouse>();

Then of course, valid values for an IMoveable are a Chimp, Marmoset, or even another Mouse, while of course you can only use a Mouse for the second type.

Hopefully this has given you a better idea of what you can do with generics.

View more entries