2 desktops, mesh, C#, C# 3, C# 4, .net, dot net, development, software engineer, developer, software

C# 3.0 Extension Methods

December 31st, 2009

What and Why?

Want to add a method to a string?  Want to allow an XmlDocument to load from your Foo class?  Well until now you’d have had to either derive your own class from string or XmlDocument, place a method on your Foo class or create an obscure static helper class to contain these methods, doing nothing for the cohesion of your design.

Extension methods have changed all this as they provide a mechanism to “add” a method to an existing class without having access to source code of the original class.  The client code knows no difference between a conventional instance method and an extension method and methods can be added to existing classes without code needing to be recompiled unless it makes use of the new method.

C# 3.0 – Real life example

We used Team Foundation Server 2008 (TFS) for our builds and each project had the potential to build for several different clients, so each build definition would actually contain say 20 build configurations.  Using the TFS API I wanted to be able to get a list of the customer configurations that a build contained so that we could select a build for an individual customer and then schedule the rest of the builds for overnight execution. 

What I needed was a “GetBuildConfigurations” method on an existing IBuildServer interface.  The code below is what I came up with:

public static class IBuildServerExtensions

{

    public static List<string> GetBuildConfigurations(this IBuildServer server, string teamProject, string buildDefName)

    {

        List<string> ret = new List<string>();

        // Get the build def XML

        string buildFileContents = GetBuildProjectContents(server, teamProject, buildDefName);

 

        // Find the list of configurations ready to return

        XDocument doc = XDocument.Parse(buildFileContents);

        if (doc.Root != null)

        {

            // Loop through each matching configuration and add the name to our list

            ...

        }

        return ret;

    }

}

 

// Client Code

[WebMethod]

public string[] GetBuildConfigurationList(string teamProject, string buildDefName)

{

    IBuildServer buildServer = Server.GetService(typeof(IBuildServer)) as IBuildServer; // Server is a property that returns a TeamFoundationServer object

    return buildServer.GetBuildConfigurations(teamProject, buildDefName).ToArray();

}

 

Let’s go through the code:

  1. The class containing the extension method is static.  It has to be this way.
  2. The class name follows no rules except my own naming convention.
  3. The extension method is static although the client code uses it as an instance method.  It too has to be this way.
  4. The first argument is preceded by the keyword “this” and the argument type is the type that is to be extended.  This is mandatory.  So, if you are adding a method to a string class the code would be:
    public static class StringExtension

    {

        public static void AdditionalMethod(this string instance)

        {

            // Do something

        }

    }

  5. The rest of the method is the same as any other method.
  6. The client code does not deal with IBuildServerExtensions it only deals with IBuildServer.
  7. The client code calls the GetBuildConfigurations method as if it was part of the original IBuildServer interface definition.

Rules

  1. Extension methods are defined as static methods.
  2. Extension methods can only be declared in non-generic, non-nested static classes.
  3. You can extend classes or interfaces.
  4. More than one class can provide extension methods for the same class and can both be used by the same client code.  E.g. Class1 and Class2 can both provide extension methods for string.
  5. Extension methods are made available by adding a reference to the containing assembly and namespace as normal.
  6. Existing methods can be overloaded but not overridden using extension method.
  7. Both an existing instance method and an extension method can have the same signature!  The extension method will never be used however because the instance method will have a higher priority at compile time.
  8. You have no magic access to the internals of the class or interface that you are extending.  You only get access to the public and internal entities as normal.

Summary

Extension methods allow you to add those much sort after missing methods to existing classes and interfaces.  This is very cool but should not be mistreated.  Adding methods to the wrong classes will damage your design, reputation and ultimately the code that you are working on, so as always, know your tools but don’t use a hammer all over the place.

Read more here.

C# 3.0 Object and Collection Initialisers

March 3rd, 2009

These are basically a syntactic shorthand for constructing and initialising an object or collection in one statement.

Consider the example where a class has only a default constructor but you need to set certain properties before you can use it as you wish. The C# 2.0 and 3.0 versions of the code that you would write are:

C# 2.0

MultProps props2 = new MultProps();
props2.Name = “Fred”;
props2.Value = 1;

C# 3.0

MultProps props32 = new MultProps { Name = “Blogs”, Value = 2 };

As you can see from this simple example, construction and initialisation can now be performed on a single line.  It’s worth noting that the normal empty bracket syntax may also be used but this is not needed, which means that object initialisers can also be used with constructors that require input parameters:

MultProps props32 = new MultProps() { Name = “Blogs”, Value = 2 };

The above are examples of object initilisers.

Collection initialisers follow the same concept but apply to all new instances of classes that implement the IEnumerable interface.  This means that collection initialisers will work on all collections from loosely typed Arrays to a strongly typed List<> objects right through to your own home-grown collections:

C# 3.0 More Object Initialisers & Some Collection Initialisers

// No constructor used, 2 properties
City nottingham = new City { Name = “Nottingham”, Celsius = 15 };

// Constructor used + 1 property
City sheffield = new City(”Steel production”) { Name = “Sheffield” };

// Default constructor + 1 property
City derby = new City() { Celsius = -6.2 };

// Object initialisers

// Strongly typed
List<City> cities = new List<City> { nottingham, sheffield, derby };

// Two-dimensional array
City
[][] cityGroups = new City[][]
{
new City[]{nottingham, sheffield, derby},

// Includes a null entry
new City[]{new City(){Name = “London”}, null}
};

Object and collection initialisers can be used in the following situations:

  1. With any accessible fields or properties - so public/internal variables (spit) in addition to public/internal properties.
  2. With named types.
  3. With anonymous types.  This is actually the only way that an anonymous type can be initialised.

NOTE: There’s a little strangeness going on.  The MSDN documentation states that “It is a compile-time error to use a collection initializer with a nullable struct”.  So why does the following work (compile and run)?

internal void NullableTest()
{
StructCity? nullAbleA = new StructCity { Name = “Won’t work” };
List<StructCity?> nullableList = new List<StructCity?> { null };

foreach (StructCity? a in nullableList)
{
Console.WriteLine(a.HasValue);
}
}

In the example above I am clearly using both object initialisation and collection initialisation on a nullable struct but I get NO compile error and I can enumerate all the elements later.  Am I missing something?

Oh well, I seam never to use structs anyway.

More details can be found here.

To read about more C# 3.0 enhancements click here.

C# 3.0 Implicitly Typed Local Variables

March 2nd, 2009

Implicitly Typed Local Variables are strongly typed variables that you define used the keyword var instead of the name of your type:

var i = 5;

The type is then inferred for you by the compiler by looking at the type of data that you populate the variable with.

WARNINGI have already had the situation where developers think that this feature is here to prevent them from using the conventional manner of instantiation anywhere in their programs.  IT IS NOT!  Whilst vars have their uses, you should not have to hover your mouse over a variable to know its type, no matter how “pretty” you think that your code looks! If you do not need to use a var then don’t use a var.

Implicitly Typed Local Variables have been introduced (IMHO) to enable anonymous types and to ease the use of LINQ.  They can be used with the following types:

  1. Built-in types.
  2. Anonymous types.
  3. User-defined types.
  4. Any type defined in the .NET Framework class library.

They can be used in the following situations:

  1. With local variables.  Var cannot be used for instance or class variables.
  2. In a foreach statement.
  3. In a using statement.

The examples listed below show the compilation-valid uses separated into what I would consider to be good and bad uses (the clue is in the method names):

private void GoodUses()
{
// expr is compiled as IEnumerable<Customer>
// or perhaps IQueryable<Customer>
var expr = from c in GetCustomers() where c.City == “London”
select c;// The type returned could be complex and hard to track down
foreach (var customer in GetGroupedCustomers())
{
if (customer.City == “London”) break;
}
}

public void PoorUses()
{
var i = 5; // i is compiled as an int
var s = “Hello”; // s is compiled as a string
var a = new[] { 0, 1, 2 }; // a is compiled as int[]
var list = new List<int>(); // list is compiled as List<int>
}

private void OnlyWayToDoIt()
{
// anon is compiled as an anonymous type
var anon = new { Name = “Terry”, Age = 34 };
}

You cannot use Implicitly Typed Local Variables in the following cases:

  1. As an instance or class variable.
  2. As a return parameter in a method.
  3. As an input parameter to a method (unless used as input to a Lambda expression).
  4. When the variable is not declared and initialised in the same statement.
  5. When the variable is used in its own initialisation (although I’m not sure I’d be happy with any of my developers doing this anyway).
  6. In multiple defined variables in the same statement.
var GetAsVar() { return 1; }  // Cannot be a return parameter
void SetAsVar(var v) { int i = v; } // Cannot be an input parameter
private var _notAllowed; // Cannot be an instance variable
private static var _alsoNotAllowed; // Cannot be a class variableprivate void NotAllowed()
{
var foo;        // Must be initialised
foo = “Hello”;

var i = (i = 20); // Cannot be used in an initialisation statement
var a, b, c = “Multiple”;
}

A little GOTCHA is that if you’ve decided to name one of your types var for some reason then firstly shame on you and secondly, any attempt to use the keyword var will then result in the compiler attemtping to declare a variable of your type and NOT of an Implicitly Typed Local Variable.

More details can be found here.

Note that a lot of the code samples have come from Microsoft and as such I am obviously NOT taking credit for them.

To read about more C# 3.0 enhancements click here.

C# 3.0 Auto-Implemented Properties

February 20th, 2009

This is a minor but useful enhancement in my opinion in that auto-implemented properties solve a couple of problems.

The first is the age old pain that has been around since at least the C++ get and set method days, where a property is merely a thin layer hiding your data, you used to have to write all the standard plumbing code yourself.  Now you don’t have to.

C# 2.0 Example

public string ExampleText
{
get { return _exampleText; }
set { _exampleText = value; }
}private string _exampleText;

C# 3.0 Equivalent

public string ExampleText
{
get;
set;
}

You can see in the C# 2.0 example that you have to write the body of the get and set properties yourself, in C# 3.0 you merely declare the property in the same way that you would in an interface.

The compiler will then create a private anonymous variable of the correct type and tie it to the property for you.  This variable can only be accessed via the property but if your design evolves and you need to provide your own implementation later then you can do so.

You must specify BOTH the get and set accessors in order to have the compiler auto-implement the properties for you.

Access Modifiers

The second problem that has been solved is one of access.  Due to get and set properties being manually implemented as separate methods in unmanaged C++, it was possible and usual to specify a public get method and a private/protected set method.  This has now been implemented for properties in C#.

public string ExampleText
{
get;
private set;
}

The above example shows that it is possible to override the access modifier on either a get or a set method.  The property must however adhere to the following rules:

  1. If you are going to set the access level on the get or set declaration, the level specified must be different to that specified on the property iteself.
  2. You cannot specify access modifiers for BOTH accessors (both get and set).
  3. The access modifier on an accessor must be MORE restrictive than the property as a whole.

Each of the rules above are broken in the examples below:

string SameAccessibility { get; private set; } // private is the default
public string TooManyAccessors { internal get; private set; }
private string LessRestrictive{get; public set;}
string OnlyOne{get;} // Error caused by only one accessor being specified.

To read about more C# 3.0 enhancements click here.

C# 3.0 Enhancements (brief summary)

February 17th, 2009

As part of looking at the C# 4.0 CTP, I thought I’d best get up to speed with the previous “improvements” provided to C# in the guise of C# 3.0.  These are:

  1. Auto-Implemented Properties. You no longer have to write the standard plumbing code (get{return _x;} or set {_x = value;}).  Declare the property as you would in an interface and C# 3.0 will do the rest.
  2. Implicitly Typed Local Variables. Strongly-typed variables who’s types are inferred at compile time by looking at the value you assign.
  3. Implicitly Typed Arrays. Same as above only for arrays.
  4. Object and Collection Initialisers. A short-hand to creating and initialising types in one step.
  5. Anonymous Types. Define and initialise a new type of object on the fly at run-time.
  6. Extension Methods. You can add your own methods to other people’s classes without recompiling their code.
  7. Lambda Expressions. The next step in anonymous method evolution.
  8. Query Expressions.  LINQ.  Allows the developer to query constructs from within their code in a similar manner that a DB developer would query a database using SQL.
  9. Expression Trees.  A “tree” of elements that represent an expression that can be compiled and executes at run-time.

These enhancements are of varying use and scariness and are worthy of investigation.  Expression trees have the power to transform the world whereas implicitly typed variables have the power to make lazy developers even more lazy and poor code even worse.

Already I find myself telling off developers who have completely removed any standard variable definition in favour of needlessly using implicitly typed variables and it is driving me mad.  Too many times developers see a new feature as the only feature and use it to death, to the detriment of maintainability and common sense.  Anyway, that is for another time.

In C# 3.0 Enhancements (part 1) I’ll start to go through these new features and then jump into C# 4.0.

Staying up to date - What CPD?

February 15th, 2009

Even before PDC 2008 I was starting to feel out of the loop. After developing in C++ for seven years I moved over to C# and needed to get to grips with not just the language but the whole framework.  Four years later and this still had not happened.  There was always something that I didn’t know, yet the work I was doing meant that as always, I only ever touched a fraction of what was available.

At the start of 2008 I was working in Spain and decided to cut my loses and learn the new stuff.  This meant that I could start to look forward to investigating all the new things that had shipped with .Net 3.0 (WCF, WPF, WF); even then I had a lot to get my head round.

However fate played its part and we moved back to the UK in March 2008, which promptly put a stop to my plans of keeping up to date.  I joined a company specialising in applications for Windows Mobile and whilst the new server-side code was C#, I was left on the legacy C++ stuff, concentrating on finding and fixing memory leaks, introducing smart pointers and thread synchronisation and generally trying to get the build and release process sorted out.

So now here we are in early 2009 and I’m finding the task of staying up to date technically, insurmountable. The only way to do this is to make a list and the list will have to be in a general priority order, which will probably change.  I can’t tackle everything at once though (or everything ever) but I have two projects that I’ll need to start soon, so they’ll be my motivators.  They should help to show what is important and thus drive what gets looked at first.

Project 1 - Windows Mobile

This project is a new version of our mobile product.  It takes work from a customer’s system and displays it to a user on a mobile device.  This will be written in C# using both the full and the compact frameworks and have to:

  • Take data from a user’s system.  At a minimum this means some XML conversion to convert the customer’s data into our format and back again.
  • Get the new data onto the client and update the user’s system with a response.  This sounds simple with the Synchronisation  Framework.
  • We don’t want to host the data ourselves.  This sounds like Azure.
  • The work that the client has to do is configurable and is basically a list of steps with input and output.  This sounds like Work Flow (WF).
  • The whole lot has to communicate.  Enter Windows Communication Foundation (WCF).
  • We’ve got to interact with a non-expert user on the mobile device.  Could be Silverlight but currently that requires permanent internet access on a mobile device, so we might have to stick with WinForms (which I know).  What about Windows Presentation Foundation (WPF)?
  • The mobile client will still need some form of business model but will be driven from the database.  This brings the Entity Framework into play.  It’s had some bad press but I still need to look at it.

Project 2 - Administration Dashboard

This is a long overdue system and whilst we want it to to work with our current product, we’d like to host it in Azure and swap out the back end in time to work with the new version of the product.  So, we are looking at:

  • The front end.  This IS going to be Silverlight.  Management like the pointy-clickyness of it and whilst I’d like to keep ASP.net as a back-up, “we’ve” (not me) have sorted out all the potential problems with Silverlight that we could see.  Ok, versions of a new technology like this are never new for long but I’d best get up to speed with SilverLight v2 whilst I can.
  • Hosted in Azure.  So Azure again.
  • Comms will be needed.  WCF again.
  • Abstraction from the data store.  Entity framework again (I think).

OK, where to start?  I’ve already programmed in C# for 4 years before returning to C++ so this should be the easy bit.  Let’s start there:

C# 3.0

  • New C# features (vars, extension objects, LINQ etc).
  • Using extension objects with XSLT looks like it’ll give a potential solution to the XML conversion.

C# 4.0 CTP

  • Dynamic types and whatever else there is.

Azure Services Platform

I’ve already been on what I believe to be the first workshop of its kind in Azure, so it makes sense to follow this up:

  • Write up the workshop.
  • Complete the labs.
  • Understand how to get a URL to point to the cloud.
  • Use Azure to host some HTML.
  • Use Azure to host some Silverlight.  I’ve already got as far as producing a bouncing ball in Silverlight so I’ll use this.

Silverlight

Silverlight on its own is no good for me.  It needs to get data dynamically.  I’ve already done a lot of the demos on design and standard “Flash” activities, so now it is time to look at Line Of Business needs:

  • Silverlight labs on Comms.
  • A little Silverlight app.
  • A WCF service.  Cool, WCF has been covered a little now too.

Entity Framework

  • Labs at this stage should be enough to decide if I need any more of it.

Sychronisation Framework.

I’ll need to understand this a lot and especially from the Windows Mobile world.

  • Labs
  • Implement my own synchronisation end points and understand when to do this together with what the implications are.
  • Check support in the compact framework.

Work Flow

I’ve got to get past the labs this time.

  • Labs
  • Small test application showing our standard entities.
  • Control the designer to allow novice users to implement their own flow (within my defined limits) to drive the test application in different ways.

WPF

Is there any need to cover this now that I have done some Silverlight?  Probably not until I need to.

That’s it!  By targeting what I learn along the lines of what I need the technologies for, I have a fighting chance of keeping my skills up to date whilst taking advantage of the latest technology to put together functional applications that our customers will actually want to use.

Still a whole lot of work though.  Help!

Live Mesh Beta - Two Desktops!

February 14th, 2009

This is daft!  The Live Mesh looks fantastic and the implications are even better.  I have however, still managed to get myself into a mess.

I first connected my home machine (Harrold) to the Mesh and played around a little creating folders and uploading files to the desktop.

Right then, what about connecting other devices?  Adding my work desktop and work laptop machines to the mesh was easy and worked as expected until I realised that I could not see the folders that I had created on the desktop.

Hold on a minute, looking at the list of devices from the pop-up off the system tray, showed that there was something strange going on.  When viewed on my work machines, the pop-up showed the desktop and both the work machines but Harrold only showed the desktop and Harrold.  What’s going on?

  • The work machines are XP and Vista where as Harrold is XP, so the client OS isn’t the problem (not that I would have expected it to be).
  • I’ve only got 1 Windows Live ID, so that’s not the issue.

However, looking at the system tray pop-ups alongside each other shows a couple of possibles:

Both sets of device lists
  1. “Live Remote” is not currently enabled in the Live Framework sandbox” on Harrold.
  2. Beta vs Tech Preview?  What happened there?  Does it make a difference?

Well the “Live Remote” is just the name given to the facility that allows you to control a remote machine in the same way and using the same protocol, as is achieved using the traditional Terminal Services, now called Remote Desktop (MSDN Blog).

Point 2 is the reason for my problems.  The difference between the Beta and Tech Preview versions is not just a different Live Framework Client.  The live desktop link goes to a completely different location:

Getting Harrold onto the same environment as the work machines became easy.  I just needed to uninstall the Live Framework Client (I still managed to mess this up a little and had to wipe some registry settings myself), reboot and then add Harrold as a new device in the normal way.

Sorted!  Just need to figure out how to port the folders from the CTP desktop into the Beta (final) desktop…

Update - that bit was easy. The original desktop folders were saved to Harrold’s disk. I just copied them into the new Mesh folder location for the Beta and they appeared on the Live Desktop. Easy.

Windows Azure CTP Usage Limits

February 13th, 2009

I’ve just attended a workshop on the Azure Services Platform in London, which will get a write -up.  Before I do though, I need to get these usage limits down.  These are the ones provided when you sign up to the CTP and receive your invitation code to Windows Azure.

  • Total compute usage: 2000 VM hours
  • Cloud storage capacity: 50GB
  • Total storage bandwidth: 20GB/day