Thursday, January 04, 2007

There is a very useful class in the .NET framework that allows you to cancel an event from the handler perspective. This class is the CancelEventArgs. Typically using this class looks as follows:

event EventHandler<CancelEventArgs> Click;
void OnClick()
{
    CancelEventArgs e = new CancelEventArgs();
    Click(this, e);
    if (e.Cancel)
    {
        // do nothing
    }
    else
    {
        // do something
    }
}

void ClickHandler(object sender, CancelEventArgs e)
{
    if (something)
    {
        e.Cancel = true;
    }
}

BTW: I have no idea why Microsoft defined CancelEventArgs under System.ComponentModel namespace.

Simple and easy. But there is a problem. What if there was a second handler for the Click event?

void ClickHandler2(object sender, CancelEventArgs e)
{
    e.Cancel = !IsValid();
}

In some scenarios, the ClickHandler2 would override changes made by ClickHandler - i.e. it would set Cancel property to false in case the state was Valid. I strongly discourage you from ever setting Cancel property to false! The problem is that in the handler method you never know if you are the only one handler or are there more handlers involved! If a previous handler had already cancelled the event you will lose this information!

In order to prevent potential mistakes, I propose an alternative version of CancelEventArgs. The version that will prevent you from making a mistake. Below is a how such a class could look like:

class CancelEventArgs : EventArgs
{
    bool cancelled;
    public bool Cancelled
    {
        get { return cancelled; }
    }
    public void Cancel()
    {
        cancelled = true;
    }
}

Notice that the Cancel property is now called Cancelled and is read-only. To Cancel an event you use the Cancel method which works only one way - there is no way to accidentally set Cancelled to false. The safer, the better :-)

kick it on DotNetKicks.com

Thursday, January 04, 2007 10:34:37 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [4]  | 
 Thursday, December 21, 2006

I have found a post on Web Development Team's blog providing SOME information on what was changed/fixed with the new Service Pack. There is also another post on Scott Guthrie's blog on the same topic. Good!

But wait! Am I really expected to look all over the Internet and gather pieces of information just to build a list that SHOULD be available in a KNOWN and EASILY ACCESSIBLE location? You got to be kidding!

Thursday, December 21, 2006 8:33:04 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

For some time now I have been having problems with "Connect To Server" window of Microsoft SQL Server Management Studio. The standard problem is that has problems remembering the password, or rather it has a habit of forgetting. The effect is that each time I run the MSSMS, there is a chance that my password will not be there even if I have checked the check box to remember it before. I'm currently running Windows 2003 Server, but I had exact the same problem on Windows XP.

Over a time I've got used to it and I no longer bother to check the "Remember Password" check box. Today however I have began to have a new suspicion.

Almost every time I try to log in to the server for the first time, I get a message that login or password was incorrect. I have always reentered my password thinking that I had made a typo. Some times it took me three times to get it right and that made me think.

Why is that window different? When I use the same password for other windows, my success/error rate is almost zero. Here I'm far from that. So I've investigated the issue.

The goal was simple: after entering a user name and password and getting a failed login attempt saying that the user name or password was incorrect, check if the message is right. Options were just to retry without changing anything or compare the entered text with what should be entered.

The first method was too easy :-). So I have decided to see what's in there. User name was a plain text so it was easy. And since it IS remembered, I have confirmed no error there. As for the password. I have used the Runtime Object Editor, to look under the hood. And guess what? Password was also correct!

Given the investigation I can say with certainty that there is a bug in the MS SMS! Such a simple function and it doesn't work!!! I have found one similar bug report. Not exactly the same but I think it is somehow connected. Imagine that. Big company, lots of money, lots of time, one small window and so many bugs!

kick it on DotNetKicks.com

Thursday, December 21, 2006 12:41:53 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [6]  | 
 Tuesday, December 19, 2006

Now I have a brand new Visual Studio 2005 Service Pack 1 installed. I'm happy with it, but I would be even more happy if I knew what was fixed by the installation. And so I went searching.

After a while, I just gave up! It is just to hard for me to accomplish the task of finding some kind of change log for the Service Pack 1! What I have found were Visual Studio 2005 Service Pack 1 release notes. On this page hidden in the summary section, just before a list of requirements and a very long list of installation issues, there it was, the link to What’s New in Visual Studio 2005 SP1. I have followed the link.

On the destination page one thing caught my attention - the topic: "What's New in Visual Studio 2005, This topic has been updated for Visual Studio 2005 SP1". Scrolling down a little, confirmed my suspicions. It is not a list of new features or bug fixes that were distributed with the new Service Pack 1. It is an overview of features the Visual Studio has now, after you install SP1. More Over! Look at the "New in Visual Studio 2005 SP1" section!!! Its empty.

I don't suppose that Microsoft is so evil not to provide some kind of change log. I only know that they just cannot make their own website usable and put the interesting things somewhere where people can actually find them. So, if anyone knows where can I get the list of features introduced with the new SP1 and the list of bug fixed, I would be grateful if he shares the knowledge.

kick it on DotNetKicks.com

Tuesday, December 19, 2006 7:52:33 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

One more time Microsoft has proven that they just cannot do things right. This time it's all about the newly released Service Pack 1 for Visual Studio 2005.

I'm certain that most of the developers working with Visual Studio 2005 know about the fact that the Service Pack has just been released. If not, at least they are aware of the fact that Microsoft was planning to release the product for some time now. So now it has been released. Are you ready to install it? Try! I have tried and it was not an easy task!

When first I have read that it is available I didn't think long before I went to the www.microsoft.com site. There I have used the search function in hope ... I don't even know what I had hoped for, given my previous experiences with searching Microsoft's site using Microsoft's search engine. The search results were disappointing yet not surprising - couldn't find it:


I have even tried to exclude the "beta" word, but with no better effect:

So, as usual, when I need to find something on Microsoft's site, I used Google (!!!). No surprise here, first result - a hit:

Having the page I went downloading. After starting the download I was presented with a funny page telling me that people who have downloaded Visual Studio 2005 Service Pack 1 have also downloaded ... Visual Studio 2005 Service Pack 1. What a coincidence :-)

After few hours of download (it has 450MB) I could finally run the setup and wait for few hours (or so according to the information on Microsoft's page) until it installs .

I had the setup procedure up and running and. Oh no! They have worked too long on this product to just let it install in like that! After a couple of minutes of waiting I've been presented with an error message Error 1718 some file did not pass the digital signature check:

What's going on? I'm sure most of us don't bother to read the installation procedure on the download page, especially as it is presented below download button, after clicking which you are redirected to another page, but there there is an information that such a problem may occur. Unfortunately, until you try installing SP1 on your concrete system, you don't know if you need to follow the procedure and by that time you have already lost a dozen of minutes. After pressing OK - the only available option, the Setup Procedure went through the same steps as before - i.e.: I had to agree to the same license terms etc. This time though it took more than ten times the amount of time just to inform me about the same problem once more!

After following the procedure I was finally able to install the service pack, after wasting a lot of time on it.

BTW: Since I haven't changed anything in my default Windows 2003 installation it seams to me that many people will have the same problem with the new Service Pack as I had!
If I count the time I have spent on trying to install the Service Pack and multiply this by the number of people that might have the problem I get a rather big number. Who is responsible? (Again! Last time it was because of IE7 that many people lost a lot of time because of the problems installing it and yet more (all) suffered from incredibly long installation time not to count few restarts and 2 validations during the process).

The question remains: why Microsoft, given all its resources, can't make it right the first time? (or second for that matter). Why they have to have everything so tightly integrated in to the operating system (like IE)? It is like if I had a house and my TV was integrated with it!

kick it on DotNetKicks.com

Tuesday, December 19, 2006 7:39:58 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, December 07, 2006

In my recent article on Immediate Window, I have showed how you can use it to debug your application, but also how to run arbitrary code. Working with Immediate Window has one major drawback: it requires a lot of typing without any kind of support from the IDE. There is however an alternative way to call your methods using Visual Studio: Object Test Bench.

Object Test Bench as the name suggests is used to test objects. It has a simple visual interface that makes it easier to work with than with Immediate Window. For example if we have a class:

public class SomeType
{
  public string SomeMethod()
  {
    return "return value"
  }
}

Then we can add an instance of this class to the Object Test Bench, and execute any of its methods using context menu as on the picture below:

 

If method that is to be invoked requires parameters, Visual Studio will display a special dialog box where you can enter appropriate values - or select them from the list of other objects if necessary. Also, if the method has a return value, the result will be added to the Object Test Bench as a new object on which you can also invoke methods.

To use the Object Test Bench, go to the Class View (ctrl+shift+c), navigate to a class you want to test and from the context menu, select "Create Instance" or "Invoke Static Method" depending on what you are trying to test. You can also access the same functionality through the Class Designer (Class Diagram).

As good as the Object Test Bench may appear to be, there are also some major problems with it that in practice make it useless - at least for me.

The first and most serious problem that disqualifies the bench is the fact that any time you make a change in the code, the whole object structure is deleted from the bench. Just imagine spending couple of minutes setting objects up just to find out that one of the method requires changes. After you make the change, you have to set the whole bench from the beginning. Immediate Window does suffer from the same problem, but it is a lot easier to just run the same command sequence by pressing UP or DOWN arrows. You cannot do this in the Object Test Bench.

The second problem is that the Object Test Bench is only accessible through the Class Diagram - which I don't use and through the Class View - which I also don't use - I only work with Solution Explorer. It may not be big problem, but it requires an additional step to use the feature. Compare this to almost immediate access to Immediate Window and multiply by the number of times you use the feature.

Third problem is that you may not see the Object Test Bench at all! Some times it happens, that when you try to "Create Instance" of an object either through Class Diagram or Class View, there is no such function in the context menu! (BTW: Visual Studio is known to hide its features randomly). In my case the problem was that I had a Web Project selected as a startup project. Changing it to an class library solved the problem. Once again there is no such problem with Immediate Window.

So basically you can use both tools: the Immediate Window and the Object Test Bench. Both have their advantages and disadvantages, but I have found the Immediate Window to be just better, faster and always there and that is why I'm not using the bench any more.

kick it on DotNetKicks.com

Thursday, December 07, 2006 7:51:19 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, December 05, 2006

In one of my articles I have written about using Immediate Window for debugging purposes - how we can use this Window to debug an application without starting it. Basically you can use the Window, to start a debugging process on any of your methods just by invoking it in Immediate Window:

new MyNamespace.MyType().MyMethod()

or for static methods just

MyNamespace.MyType.MyMethod()

There are however other useful features that make this window even more powerful.

One of them is evaluation of commands. Take for example:

System.Guid.NewGuid()
{04653f8d-58d3-4254-adc8-fb6d95457b49}

Which presents you with a new Guid instance as a string. Nice feature to have since I'm no longer able to find the Generate Guid window in my Visual Studio 2005. This window was very useful when I was working with Visual Studio 2003.

The above is simply a static method call. Lets see what else can we do. The immediate window can be used as a simple (or very advanced when you think about it) calculator. Take for example:

5*5
25

What we get in return is... of course the result of this operation. Still this is also a method call underneath. We can go very far with this, as far as the .NET classes allows us to. If we need an advanced calculator we can use some of the Math's methods:

System.Math.Sqrt(4) + 3.2
5.2

Those are still only simple method calls. The interesting part begins with multi-line statements!

The immediate window allows commands to span multiple lines and include variables. With those you can do almost anything you could do in the normal code:

int x = 2;
2
int y = 3;
3
x + y
5

If you wonder how far you can go with Immediate Window, just consider this example:

System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection("someconnectionstring");
System.Data.SqlClient.SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM SomeTable";
connection.Open();
System.Data.SqlClient.SqlDataReader reader = cmd.ExecuteReader();
reader.Read();
reader[0];

Not that you will use the window for such commands, but it is nice to know what it can really do :-)

BTW: I have noticed that sometimes Visual Studio hides the Immediate Window from me. While doing so it also removes the one place in the menu that I know of that can be used to show the window: Debug->Windows->Immediate. If your Visual Studio also knows better, the shortcut Ctrl+Alt+I will help you.

kick it on DotNetKicks.com

Tuesday, December 05, 2006 9:29:12 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, November 23, 2006

Today I have recieved a comment on my article on Optimizing Rendered Page Size, that it is not possible to override the LoadPageStateFromPersistenceMediummethod of a Page class because it is marked as internal in ASP.NET 2.0. Strange thing was that I have made just that in one of the projects I have been working on with ASP.NET 2.0! So I went for some searching.

First thing I have checked the code to see if it really compiles with the override - it did. There is even a support from Intelisense for overriding this method. Next I want to see if the is LoadPageStateFromPersistenceMediummethod really internal. Using reflector I have been able to confirm this. It really is "protected internal virtual". So the question is: how am I able to override it?

The reason we are able to override such a method is that "protected internal" is an OR relationship which means that such a member is accessible in the types that derive from our type AND in all types defined in the assembly. This should make it clear why we are able to override this method.

What may be less clear is why overriding "protected internal" requires sometimes "protected override" instead of "protected internal override". If you read once more the definition, it clearly states that protected internal is accessible to sub-types and the assembly. So if you want to override a method in the same assembly you would use "protected internal override". If on the other hand you want to override this method in other assemblies you must not use the "internal" access modifier because it would make the method visible to every type in your assembly - which would in fact change the visibiliti of the method. This would of course result in an error from the compiler. In this case you would get the CS0507 error.

I hope this sheds some light on the issue.

kick it on DotNetKicks.com

Thursday, November 23, 2006 2:15:34 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

Following my last article on IComparable vs IComparer interfaces I now present a common pattern that I have found to be very effective in terms of code usability.

In order to make working with IComparer implementing classes more natural and intelisense friendly I usually create the inner classes of the main class and expose the objects as as static properties or methods. The following example demonstrates:

public class Person
{
  int age;
  string name;
  public static IComparer<Person> GetPersonAgeComparer()
  {
    return new PersonAgeComparer();
  }
  public static IComparer<Person> GetPersonNameComparer()
  {
    return new PersonNameComparer();
  }
  private class PersonAgeComparer : IComparer<Person>
  {
    #region IComparer<Person> Members
    public int Compare(Person x, Person y)
    {
      return x.age.CompareTo(y.age);
    }
    #endregion
  }
  private class PersonNameComparer : IComparer<Person>
  {
    #region IComparer<Person> Members
    public int Compare(Person x, Person y)
    {
      return x.name.CompareTo(y.name);
    }
    #endregion
  }
}

Now when you need to sort a collection of Person objects you just get the right IComparer from the Person's static Get*Comparer methods. Notice that the IComparer classes are defined as private so the only way to create them is through the factory - like static method. Making the classes private is nice a way to prevent Intelisense from unnecessary displaying them when what we really need is the concrete object. Notice the use of generic interface, which is new to the .NET Framework 2.0. You could also use the partial classes feature to put the comparers in a separate file if necessary.

kick it on DotNetKicks.com

Thursday, November 23, 2006 1:25:33 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, November 22, 2006

In .NET some of the collection types such as Array, ArrayList, List<T> expose the Sort method that allows you to sort the collection. In order for those classes to sort the collection, there has to be a way for them to somehow compare objects with each other. The most basic Sort method usually does not require any arguments other than the collection itself in case of the static Array.Sort. In this case how does the framework know how to compare our objects? Is person1 greater than person2? Or maybe they are equal?

Enter the IComparable interface. By implementing this interface, the objects of the type become, as the name suggest, comparable, so now it is possible to compare person1 to person2 using a simple person1.CompareTo(person2) call. With this each Sort method can easily handle sorting. An example implementation of sort method is included in the MSDN documentation.

So what is wrong there? If you take a Int32 objects, a String object, the IComparable interface on those is pretty straightforward and self explaining. It is plain even to a non-technical person that 1 < 3 and "abc" = "abc". But what about a more complex types such as a custom Person type that represents a person in the real world.

What does it mean for one persons to be greater (or equal for that matter) than the other? It does not mean anything without a context, a criteria by which we compare the two. So for example if were to compare the age of both persons, we would be able to say if who is older (greater) or younger (lesser). We could compare their names, their salary or whatever, but we need to know the criteria before we start.

Suppose that we have a class definition of Person as follows:

public class Person : IComparable
{
  int age;
  string name;

What does it mean for an object of this class to be comparable to each other? Is the name used? Or maybe the age? The fact that we don't know! The only way to know is to check the documentation or the implementation of the CompareTo method. First one goes against the rule I like to follow that states that the code should be self documenting. In this case it isn't. The second option breaks the rule of encapsulation - that is, we have to know the implementation of an object to work with it. Fortunately there is another way to compare and sort objects.

Enter the IComparer interface. This interface allows you to compare two objects in a similar way the IComparable interface does. The difference here is that it IComparer allows for much greater expressiveness. An implementation of IComparer is always a class which does have a name. This name explains (or at least it should) exactly what it does. For example:

public class PersonAgeComparer : IComparer

Makes it obvious to everyone what will be the criteria for the comparison without breaking the encapsulation. This makes your code easier to understand and much more self documenting. I strongly discourage everyone from using the IComparable interface on classes where it is not explicit what would be compared, even if it will be the only comparison made.

kick it on DotNetKicks.com

Wednesday, November 22, 2006 7:48:06 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |