Saturday, November 21, 2009

.NET 4.0 and VS 2010 Series – Named and Optional Parameters

After my posts on the framework features over the past couple of weeks, I will now start focussing on the language aspects of C# 4.0. In C# 4.0, named and optional parameters have been introduced. This is one feature that I have been waiting for so I am only glad that the .NET team has decided to introduce this feature in C# 4.0.

VB 6.0 programmers are aware of the usage of the optional parameters. It used to be declared as

 Sub DoSomething(Optional ByVal Switch As Boolean = False)
What the above declaration meant was that you could call the DoSomething method without explicitly passing the Switch parameter. The default value of false will be assigned to the variable if it was not passed.

This was not possible in .NET. The workaround was to declare overloaded methods. You do not need to do that anymore. In C# 4.0, you can declare a method with an optional parameter simply by assigning a default value for the parameter in question like the example below.

private string Extract(String inputString, int endIndex=0, int startIndex =0)


Named parameters as the name suggests, enable the developers to skip a parameter while calling the method if they wish to. This is done by passing the parameter by quoting its name and value separated by a colon as shown in the syntax below

Extract(inputString, startIndex: 4);


The syntax above calls the method extract with three parameters the signature of which is described previously. You will notice that the second parameter endIndex has been skipped and the value is being passed for startIndex. Below is the complete code snippet


   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Diagnostics.Contracts;
   6:  
   7:  
   8: namespace NamedOptionalParams
   9: {
  10:     class Program
  11:     {
  12:         static void Main(string[] args)
  13:         {
  14:             String inputString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  15:             String result = Extract(inputString,6);
  16:             String result1 = Extract(inputString, startIndex: 4);
  17:             String result2 = Extract(inputString, startIndex: 6, endIndex: 10);
  18:             Console.WriteLine(result);
  19:             Console.WriteLine(result1);
  20:             Console.WriteLine(result2);
  21:             Console.ReadLine();
  22:  
  23:         }
  24:  
  25:         //this method creates a substring based on the input parameters
  26:         //1. The input string is always passed
  27:         //2. Start Index is an optional parameter. If this is not passed then the 
  28:         //   start is assumed to be 0 which is the default value
  29:         //3. The End Index can be omitted. If it is omitted, then start Index has to
  30:         //   be passed and the string is from the start index to the end of the input
  31:         //   string
  32:         static string Extract(String inputString, int endIndex=0, int startIndex =0)
  33:         {
  34:  
  35:             if (endIndex==0)
  36:             {
  37:                 endIndex = inputString.Length;
  38:             }
  39:  
  40:             String outString = inputString;
  41:             outString = inputString.Substring(startIndex, (endIndex - startIndex));
  42:             
  43:             return outString;
  44:         }
  45:     }
  46: }

In the above example, the extract method just creates a substring for a specified start and end index. I have made three calls to the method. Note that with Named Parameters, the order in which you pass the parameters is not important as long as you don’t forget to name them correctly. You can see this in Line 17 of the above code.

That is it for this post on named and optional parameters. They are quite a useful feature that will reduce the number of overloaded methods that we will have to write. I am sure you will find more ways of putting them to use.

Tuesday, November 17, 2009

.NET 4.0 and VS 2010 Series - PIA – Rest in Peace

In previous versions of .NET, Primary Interop Assemblies (PIA) acted as the bridge between unmanaged COM components and managed code. Though PIA solved the problem of marshalling for almost all types, they came with their own problems. One of the biggest problem was that even if a small feature was used, the developer had to ship the complete PIA which is not a small payload by any means.

Also, a developer had to develop an assembly for each version of word or excel that the application targeted. This drastically increased the size and the complexity of the deployment package.

With .NET 4.0 this has changed. Developers no longer need to ship the whole PIA. .NET 4.0 gives the developer the flexibility of embedding only those features that are used by the application rather than shipping the whole assembly. This also means that the developer does not need to worry about the availability of the target applications like Word or Excel. Enabling embedded interop assemblies is very easy. You right click the interop reference and change the EmbedInteropTypes from false to True.

Enbed

When you do that, the interop assemblies are no longer referred. You can confirm this by using the reflector. The snapshot will look like below. Note that the Excel and Word are now namespaces within  the project instead of references.

Reflector

Friday, November 6, 2009

How to: Increase the size of your virtual hard disk

If you have run out of space in your virtual image hard disk and didn’t know the way out of it; read on. I ran into this problem last week and found the following solution after a bit of googling. Though there were a lot of posts targeted at VMWare, I was looking for ones specific to Microsoft VPC. The magic tool that you have to look at is called VHD Resizer. It is a free download available from the VM tool kit site. You just have to register on the site to download.

When you run the tool, it will ask you to point to the vhd whose hard disk size you want to increase. You can also set the size you want to increase it to. The only thing that needs to be remembered, is that it makes a copy of the VHD so you will need the disk space to cope with it.

When this process is complete, the next thing you have to do is to make sure your volume uses the new space allocated. You can do this by using the DISKPART command. You will find the necessary instructions here. That’s it!!! You will have your new drive with loads of space!!!

Tuesday, November 3, 2009

VS 2010 and .NET 4.0 Series – Code Contracts - II

In the first part of this series, I wrote about how you can check preconditions with Code Contracts. We also looked at some of the features of postconditions. In this post, we will implement postconditions with an example and go on to look at object invariants.

You can implement Postconditions using Contract.Ensures method. Similar to the Contract.Requires, this takes in a boolean parameter and can display a string as the error message. Unlike the Requires method, Contract.Ensures cannot throw a specific exception.

We will use the same Concatenate method that we kicked off in the first part and enhance that with some postconditions checks. Here is what it looks like

   1: static string Concatenate(string leadingstring, string trailingstring)
   2:        {
   3:  
   4:            //raise an exception if the contract fails
   5:            Contract.Requires<ArgumentNullException>(leadingstring.Length > 0);
   6:            //make sure the string is greater than 10 characters before the code exits the method
   7:            Contract.Ensures(Contract.Result<string>().Length > 10, "The string is too short");
   8:            //ensure that the concatenated string is at least longer than the leading string by 2
   9:            Contract.Ensures(Contract.Result<string>().Length > Contract.OldValue<string>(leadingstring).Length + 2, "The value of the concatenated string is not long enough");
  10:            leadingstring = String.Concat(leadingstring, trailingstring)
  11:            return leadingstring;
  12:        }



The method now returns the concatenated string. It also includes a couple of ensures statements. Note that though we are implementing postconditions, the Contract.Ensures statement should be included at the beginning of the method and not at the end. There are two checks I have done




  • The first to make sure that the length of the concatenated string is greater than 10. The Contract.Result returns the value that is being returned from the method.



  • The second check makes sure that the concatenated string is at least 2 characters longer than the leading string. Here, I have used the Contract.OldValue to get the original value of leadingstring when it entered the method.

Unlike Contract.Requires, you will not be able to catch a specific exception if the Contract.Ensures fails. In the main method, I have caught a generic exception to handle any contract exceptions. Below is my main method with the changes.





   1: static void Main(string[] args)
   2:         {
   3:             try
   4:             {
   5:                 string resultString = Concatenate("1234567891011", "a");
   6:                 Console.WriteLine("The result is {0}", resultString);
   7:                 Console.WriteLine(resultString);
   8:  
   9:             }
  10:             //catch the argument null exception raised by the contract
  11:             catch (ArgumentNullException nullString)
  12:             {
  13:                 Console.WriteLine(nullString.Message);
  14:             }
  15:             catch (Exception ex)
  16:             {
  17:                 Console.WriteLine(ex.Message);
  18:             }
  19:  
  20:             Console.ReadLine();
  21:         }

Object Invariants

Invariants are code contract features that enable you to check object state and ensure conditions are met when you call methods on these objects. To validate a class using invariants, you will have to write an Invariant method that returns void. This method needs to be decorated with the [ContractInvariantMethod] attribute.

To demonstrate the use of invariants, I have refactored the above concatenation code using an external class called StringManipulation. This class that has two public variables and one Concatenate method.


   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Diagnostics.Contracts;
   6:  
   7: namespace CodeContractsSample
   8: {
   9:     
  10:     class StringManipulation
  11:     {
  12:         public string leadingString = "12345678";
  13:         public string trailingString = "87654321";
  14:  
  15:         [ContractInvariantMethod]
  16:         protected void ObjectInvariant()
  17:         {
  18:             Contract.Invariant(this.leadingString.Length>5);
  19:             Contract.Invariant(this.trailingString.Length>5);
  20:  
  21:         }
  22:         
  23:         public string Concatenate()
  24:         {
  25:             return String.Concat(leadingString, trailingString);
  26:         }
  27:  
  28:     }
  29: }


As you can see, I have also added the CodeInvariant method to check if both the strings are at least 5 characters in length. This means that I will have to initialize the string to pass that condition. Otherwise the object does not get created.

The other consideration you will have to keep in mind when using object invariants are that the invariant checks are only done when a method call is made. In essence, invariants will not work for DTO or DataContracts. The workaround is to use Contract.Requires on the property.

Legacy If..Else Blocks

While Code Contracts are a new .NET 4.0 feature, there exists a lot of legacy code using If…Else… that does similar validations. If you want the .NET framework to treat them as contracts, you can use the EndContractBlock provided the If…Else… are the first set of statements in a method. when you use EndContractBlock, all the If..Else.. conditions are assumed as preconditions.

Code Contract Usage Considerations

Code Contracts give dev leads and architects a plethora of options to do validations. But, as with anything else, there are certain decision points that need to be taken care of.


  • Decide very early in the project how you are going to use Code Contracts. Though static checking is very powerful, it also puts a lot of drab in your build process. Make sure you are turning static checking on only when you need it.

  • You could also do runtime checking only on debug builds. This works very well for TDD projects

  • Be wary of turning on runtime checking on production builds. Remember, .NET 4.0 is still in its beta.

  • Code Contracts are very extensive. Make sure you understand all the features offered before picking on the best way to do your validations or checks.

  • When you are using both preconditions and postconditions in the same method, there is a specific order which is recommended. The order according to the Code Contract documentation is as follows

    • Legacy if…Then…Else blocks

    • Contract.Requires to check public preconditions

    • Contract.Ensures to check public postconditions

    • Contract.EnsuresOnThrow to check public exceptional conditions

    • Contract.Ensures to check all private postconditions

    • Contract.EnsuresOnThrow to check all private postconditions before finishing off with the EndContractBlock

  • You can use Contracts with pre .NET 4.0 versions by referencing the Microsoft.Contracts library. In .NET 4.0 Code Contracts have been integrated into the mscorlib.dll

  • One of the recommended ways of using Code Contracts is to have a separate config file for contracts.

  • The contracts build output can be shipped along with your build so that other developers\administrators can make use of it. Make sure you understand the different build options.

That concludes my two part post on Code Contracts and their usage. The posts try to give you a peek are by no means exhaustive on the features that Code Contracts offer. For complete understanding, I would recommend you download the manual from DevLabs and give it at least a quick skim through. Happy Coding!!!!