Archive for the ‘C#’ Category

C# 3.0 Extension Methods

Thursday, 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

Tuesday, 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

Monday, 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

Friday, 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)

Tuesday, 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.