Object Initialisers III

It seems that now I’ve got Lutz Roeder’s Reflector on the case with Orcas the way object initialisers work slightly different to how I expected.

As it was described to me as instantiating the object followed by the property calls. However, the compiler has taken some extra steps in there – no doubt on the grounds of safety.

First consider the following code:

// Create Robert Burns, DoB 25/Jan/1759
Person robertBurns = new Person { FirstName = "Robert", Surname = "Burns", 
DateOfBirth = new DateTime(1759, 1, 25) }; Console.WriteLine("{0}", robertBurns);

As I understood the feature, the compiler should have generated code that looked like this:

Person robertBurns = new Person();
robertBurns.FirstName = "Robert";
robertBurns.Surname = "Burns";
robertBurns.DateOfBirth = new DateTime(1759, 1, 25);

However, Reflector reveals that what is actually being produced is this:

    Person <>g__initLocal0 = new Person();
    <>g__initLocal0.FirstName = "Robert";
    <>g__initLocal0.Surname = "Burns";
    <>g__initLocal0.DateOfBirth = new DateTime(0x6df, 1, 0x19);
    Person robertBurns = <>g__initLocal0;
    Console.WriteLine("{0}", robertBurns);

This actually makes some sense. For example, if my new Person object was assigned to a property of something else, or passed in as a parameter to a method it wouldn’t have the opportunity to assign values to the properties on the new object. So, it constructs it all in the background then assigns it to whatever needs it, whether that is a local variable, a property on some object a parameter in a method.

For example, if the above program is reduced to just one line of code:

// Create Robert Burns, DoB 25/Jan/1759
Console.WriteLine("{0}", new Person { FirstName = "Robert", Surname = "Burns",
                                      DateOfBirth = new DateTime(1759, 1, 25) });

The compiled result will be:

    Person <>g__initLocal0 = new Person();
    <>g__initLocal0.FirstName = "Robert";
    <>g__initLocal0.Surname = "Burns";
    <>g__initLocal0.DateOfBirth = new DateTime(0x6df, 1, 0x19);
    Console.WriteLine("{0}", <>g__initLocal0);

Related Posts: Object Intialisers I and II

NOTE: This page was rescued from the Google Cache. The original date was Tuesday, 13th March, 2007

Object Initialisers II

Following on from Gary Short‘s message from my previous post on Object Initialisers, I decided to take a screenshot of Orcas displaying the tooltips.

Screenshot of intellisense showing object initialisers in Orcas

I really have to compliment those that designed and wrote intellisense. Not only does it work with object initialisers, but it is intelligent enough to remove properties that have already be used.

NOTE: This post was rescued from the Google Cache. The original date was Sunday, 11th March 2007.

Object Initialisers I

Continuing with the language enhancements in C#3.0. This post presents the concept of object initailisation.

Say you have a class with a default constructor and lots of properties and you want to be able in initialise the object in one line but the class doesn’t support it. What you can do is use object initailisers:

So, a series of calls like this in C#2.0:

Policy p = new InsurancePolicy();
p.Id = 123;
p.GrossPremium = 100;
p.IptAmount = 10;

Could now be written as this in C#3.0:

InsurancePolicy p = new InsurancePolicy {Id = 123, GrossPremium = 100, IptAmount = 10};

You’ve probably seen something similar already with respect to declaring attributes on an assembly, class or method.

Again, like the other language features in C#3.0, this is just syntactic sugar. The compiler will output the calls in a similar way to the first (C# 2.0) example.

At the moment I can’t see this feature being useful for classes that I build myself as I have control over the class’s constructors and if needed then I can accommodate the parameters as appropriate. Also, the idea of having a single line of code with so many object initialisers in it would seem to me to be a potential source of some really ugly code.

That isn’t to say this isn’t useful for my own classes – it could be used as a way of reducing the need to provide many overloaded versions of the constructor. It would no longer be necessary to anticipate every permutation and combination of properties that are needed to initialise the object past a basic valid state. It could save quite a bit of time. However, caution would need to be exercised. Any constructor created would still need to ensure that the object was created into a valid state. Using object initialisers to initialise the object completely from scratch may not be appropriate.

Object initialisers are a tool. So long as the developer remembers to use the right tool for the right job then this new language feature can be used very effectively.

What object initialisers would be most useful for, as far as I can see, would be for existing classes where I don’t have control over their makeup. e.g. Framework classes, or classes from a third party.

NOTE: This post was rescued from the Google Cache. The original date was Saturday 10th March, 2007.


Original comments:

My first thought when seeing this code was, how will this work with Intelisense?

3/10/2007 6:54 PM | Gary Short

The demonstration that I saw at the MSDN roadshow in Glasgow earlier this week shows that it works.

I would guess that because it knows what object you are instantiating as it comes directly after the new keyword it will be able to determine what public properties with setters are available.

3/10/2007 7:05 PM | Colin Angus Mackay

Cool, thanks for the info Colin!

3/10/2007 7:09 PM | Gary Short

Yep – with the March CTP intellisense for object initialization works great.

Hope this helps,

Scott

3/10/2007 11:33 PM | scottgu

A start on LINQ

I was at the Microsoft MSDN Roadshow today and I got to see some of the latest technologies being demonstrated for the first time and I’m impressed.

Daniel Moth’s presentation on the Language Enhancements and LINQ was exceptional – It really made me want to be able to use that technology now.

What was interesting was that the new enhancements don’t require a new version of the CLR to be installed. It still uses the Version 2.0 CLR. It works by adding additional stuff to the .NET Framework (this is .NET Framework 3.5) and through a new compiler (the C# 3.0 compiler). The C# 3.0 compiler produces IL that runs against CLR 2.0. In essence, the new language enhancements are compiler tricks, which is why the CLR doesn’t need to be upgraded. Confused yet?

Now that the version numbers of the various components are diverging it is going to make things slightly more complex. So here is a handy cheat sheet:

2002 2003 2005 2006 2007ish
Tool VS.NET 2002 VS.NET 2003 VS 2005 VS 2005
+ Extension
“Orcas”
Language (C#) v1.0 v1.1 v2.0 v2.0 v3.0
Framework v1.0 v1.1 v2.0 v3.0 v3.5
Engine (CLR) v1.0 v1.1 v2.0 v2.0 v2.0

The rest of Daniel’s talk was incredibly densely packed with information. Suffice to say, at the moment, LINQ is going to provide some excellent and powerful features, however, it will also make it very easy to produce code that is very inefficient if wielded without understanding the consequences. The same can be said of just about any language construct, but LINQ does do a remarkable amount in the background.

After the session I was speaking with Daniel and we discussed the power of the feature and he said that, since C#3.0 produces IL2.0 it is possible to use existing tools, such as Lutz Roeder’s Reflector, to see exactly what is happening under the hood. An examination of that will yield a better understanding of how LINQ code is compiler.

LINQ code looks similar to SQL. For example:

var result =
    from p in Process.GetProcesses()
    where p.Threads.Count > 6
    orderby p.ProcessName descending
    select p

This allows the developer to write set based operations in C# a lot more easily than before. A rough equivalent in C# 2.0 to do the same thing would probably look something like this:

List<Process> result = new List<Process>();
foreach(Process p in Process.GetProcesses)
{
    if (p.Threads.Count > 6)
        result.Add(p);
}
result.Sort(new DescendingProcessNameComparer());

* NOTE: Assumes that DescendingProcessNameComparer is an existing comparer that compares two Process objects by their name in descending order.

C# 3.0 introduces the var keyword. This is unlike var in javascript or VB. It is not a variant type. It is strongly typed and the compiler will complain if it is used incorrectly. For example:

var i = 5;
i = "five"; // This will produce a compiler error because i is an integer

In short this was only a fraction of what I learned from just one session – I’ll continue the update as I can.

Tags:

NOTE: This post was rescued from the Google Cache. The original date was Monday, 5th March 2007.


Original comments:

Glad you enjoyed it Colin 🙂

Be sure to check out the written version of my talk on my blog!

3/6/2007 11:34 AM | Daniel Moth

Automatic Properties

Continuing my look at the new features found in the C# 3.0 compiler I will look at Automatic Properties.

public class Employee{    public string FirstName { get; set; }
    public string Surname { get; set; }
    public DateTime DateOfBirth { get; set; }
    public Employee Manager { get; set; }}

At first look this might seem more like a definition for an interface, but for the class keyword and the member visibility modifiers.

However, this is actually a new feature where by the compiler will automatically fill in the member fields. This is useful for situations where nothing needs to be done when getting or setting values from the member fields. It means they can be constructed much more quickly as there is no need for tedious creating of private member fields then the public properties. All that is needed is one simple construct.

It is also possible to reduce the visibility of the getter and setter independently. For example, in the above example you may wish to make DateOfBirth to be effectively read-only for all by the class that owns it. You can prefix the set keyword with the private visibility modifier.

But what is the compiler actually producing? The following is the output from Lutz Roeder’s Reflector for the DateOfBirth property:

[CompilerGenerated]
private DateTime <>k__AutomaticallyGeneratedPropertyField2;

public DateTime DateOfBirth
{
    [CompilerGenerated]
    get
    {
        return this.<>k__AutomaticallyGeneratedPropertyField2;
    }
    private [CompilerGenerated]
    set
    {
        this.<>k__AutomaticallyGeneratedPropertyField2 = value;
    }
}

In the code, only the  property is accessible. Attempting to use the compiler generated name produces a compiler error.

If the full name (as shown above) is used then the compiler will complain with three errors:

Compiler errors
# Error File Row Col Project
1 Identifier expected ConsoleApplication2Employee.cs 20 18 ConsoleApplication2
2 Invalid expression term ‘>’ ConsoleApplication2Employee.cs 20 19 ConsoleApplication2
3 ; expected ConsoleApplication2Employee.cs 20 20 ConsoleApplication2

If the <> are removed the message changes to

Compiler errors
# Error File Row Col Project
1 ‘ConsoleApplication2.Employee’ does not contain a definition for ‘k__AutomaticallyGeneratedPropertyField2’ and no extension method ‘k__AutomaticallyGeneratedPropertyField2’ accepting a first argument of type ‘ConsoleApplication2.Employee’ could be found (are you missing a using directive or an assembly reference?) ConsoleApplication2Employee.cs 20 18 ConsoleApplication2

So, why go to all this trouble? Surely it isn’t just to save a few key strokes?

Part of the answer can be seen in a post I made in November 2005: Why make fields in a class private, why not just make them public? and there was a follow up in June 2006 when I returned to The Public Fields Debate Again.

In short, public fields and public properties, although they appear to look identical to the outside in C# are sytactically different once compiled. Automatic Properties are a way to address that. If you, at some point in the future, decide that you need the property to do more then the external interface of the object won’t change, you just turn the automatic property into a normal property/field combination again.

NOTE: This post was rescued from the Google Cache. The original date was Tuesday, 13th March, 2007.

Extensions Methods

I’ve been looking at more of the language enhancements in C# 3.0. In this post I’m going to look at Extensions.

There have been many times went a class has needed to be extended, but the additional code just doesn’t sit right on the class itself. In that case a utility or helper class is created to help carry out these mundane tasks without impacting the main class the helper operates on. It may be because the method requires access to classes that would tightly couple the main class to others.

It is important to remember that the extension method, like any method on a helper or utility class, cannot access the private or protected members of the class it is helping.

For example, take the children’s game Fizz-Buzz which seems to be undergoing a resurgence at the moment. The rules for the method are simple. The program counts from 1 to 100 replacing any value that is divisible by 3 with Fizz and any value that is divisible by 5 with Buzz. If a value happens to be divisible by both 3 and 5 then the output is FizzBuzz. For any other value the number is output.

First here is the version without the extensions:

public static class FizzBuzzHelper
{
    public static string FizzBuzz(int number)
    {
        if ((number % 5) == 0)
        {
            if ((number % 3) == 0)
                return "FizzBuzz";
            return "Buzz";
        }
        if ((number % 3) == 0)
        {
            return "Fizz";
        }
        return number.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine(FizzBuzzHelper.FizzBuzz(i));
        }
        Console.ReadLine();
    }
}

And now the version with the extensions:

public static class FizzBuzzHelper
{
    public static string FizzBuzz(this int number)
    {
        if ((number % 5) == 0)
        {
            if ((number % 3) == 0)
                return "FizzBuzz";
            return "Buzz";
        }
        if ((number % 3) == 0)
        {
            return "Fizz";
        }
        return number.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine(i.FizzBuzz());
        }
        Console.ReadLine();
    }
}

There aren’t actually that many changes (and the example is somewhat trivial).

First, in the extension method, the this keyword is placed before the parameter. It indicates that the extension will go on the int (or rather the Int32) class.

Second, when the extension method is called there is no reference to the utility class. It is simply called as it it were a method on the class (in this case Int32). Also, note that the parameter is not needed because it is implied by the object on which the extension method is applied.

Lutz Roeder’s reflector is already conversant with extension methods so the compiler trickery cannot be seen in the C# view of the method. However, the IL reveals that deep down it is just making the call as before. The following is the extension version:

L_0007: call string ConsoleApplication3.FizzBuzzHelper::FizzBuzz(int32)
L_000c: call void [mscorlib]System.Console::WriteLine(string)

And this is the old-style helper method call:

L_0007: call string ConsoleApplication3.FizzBuzzHelper::FizzBuzz(int32)
L_000c: call void [mscorlib]System.Console::WriteLine(string)

They are identical. So, how does the compiler tell what it needs to be doing?

The method header for the regular helper method:

.method public hidebysig static string FizzBuzz(int32 number) cil managed
{

The method header for the extension method:

.method public hidebysig static string FizzBuzz(int32 number) cil managed { .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor()

And that’s it. C# just hides the need for the ExtensionAttribute. In VB the attribute needs to be explicitly declared on the method.

Intellisense also helps out with extensions. Each extension method appears in the intellisense on the object it is extending. To ensure that the developer is aware that it is an extension the icon in the list has a blue arrow and the tool tip is prefixed with “(extension)”

orcas-extensions-intellisense

It is also possible to create extension methods that take more than one parameter. For example:

public static class PasswordHashHelper
{
    public static byte[] HashPassword(this string password, byte[] salt)
    {
        // Implementation here
    }
}

It is important to note that the this modifier can only be placed on the first parameter. To do otherwise would generate the compiler error “Method ‘{method name}’ has a parameter modifier ‘this’ which is not on the first parameter”

The above multi parameter extension method can then be used like this:

byte[] hashedPassword = plainTextPassword.HashPassword(salt);

NOTE: This entry was rescued from the Google Cache. The original date was Thursday, 15th March, 2007.

Anonymous Types

Anonymous Types are another new feature to the C# 3.0 compiler.

To create one, just supply the new keyword without a class name, followed by the, also new, object initialiser notation.

As the type name is not known it needs to be assigned to a variable declared with the local variable type inference, var, keyword.

For example:

var anonType = new { FirstName = "Colin", MiddleName = "Angus", Surname = "Mackay" };

It is possible to assign a new object to the variable, but it must be created with the object initialisers in exactly the same order. If, say, the following is attempted a compiler error will be generated:

anonType = new {Surname = "Rowling",  FirstName = "Joanna", MiddleName = "Kathleen" };

The corresponding compiler error is: Cannot implicitly convert type ‘anonymous type […ProjectsConsoleApplication4ConsoleApplication4PropertiesAssemblyInfo.cs]’ to ‘anonymous type […ProjectsConsoleApplication4ConsoleApplication4PropertiesAssemblyInfo.cs]’

At the moment I’m not entirely sure where AssemblyInfo.cs comes in. If anyone knows the answer I’d love to know.

Back to the original example. What does this look like under the microscope of Lutz Roeder’s Reflector?

var <>g__initLocal0 = new <>f__AnonymousType0();
<>g__initLocal0.FirstName = "Colin";
<>g__initLocal0.MiddleName = "Angus";
<>g__initLocal0.Surname = "Mackay";
var anonType = <>g__initLocal0;

But that isn’t all that was generated. The compiler also generated the following internal class (Note: Some of the detail has been stripped for clarity)

internal sealed class <>f__AnonymousType0<<>j__AnonymousTypeTypeParameter1,
    <>j__AnonymousTypeTypeParameter2, <>j__AnonymousTypeTypeParameter3>
{
    // Fields
    private <>j__AnonymousTypeTypeParameter1 <>i__AnonymousTypeField4;
    private <>j__AnonymousTypeTypeParameter2 <>i__AnonymousTypeField5;
    private <>j__AnonymousTypeTypeParameter3 <>i__AnonymousTypeField6;

    public <>j__AnonymousTypeTypeParameter1 FirstName
    {
        get
        {
            return this.<>i__AnonymousTypeField4;
        }
        set
        {
            this.<>i__AnonymousTypeField4 = value;
        }
    }

    public <>j__AnonymousTypeTypeParameter2 MiddleName
    {
        get
        {
            return this.<>i__AnonymousTypeField5;
        }
        set
        {
            this.<>i__AnonymousTypeField5 = value;
        }
    }

    public <>j__AnonymousTypeTypeParameter3 Surname
    {
        get
        {
            return this.<>i__AnonymousTypeField6;
        }
        set
        {
            this.<>i__AnonymousTypeField6 = value;
        }
    }
}

Because the developer has no access to the actual type name the an object created as an anonymous type cannot be passed around the program unless it is cast to an object, the base class of all things. It cannot, for obvious reasons, be cast back again. So at this point the only way of accessing the data stored within is via reflection, or with methods already present on object.

Anonymous types can be examined in the debugger quite easily and show us just like any other object.

Debugging anonymous types in Orcas

One especially neat feature of anonymous types is its ability to infer a name when none is given. For example:

DateTime dateOfBirth = new DateTime(1759, 1, 25);
var anonType = new { FirstName = "Robert", Surname = "Burns", dateOfBirth };

The dateOfBirth entry was not explicitly given a name on the anonymous type. However, the compiler inferred a name based on the variable name that was given. The anonymous type therefore looks like this: { FirstName = Robert, Surname = Burns, dateOfBirth = 25/01/1759 00:00:00 }

Naturally, some will dislike this as the anonymous type now has a mix of pascal and camel case for the properties it is exposing.

NOTE: This post was rescued from the Google Cache. The orginal date was Saturday, 17th March, 2007

Test Driven Development By Example

Introduction

A lot has been written on the subject of test driven development, and especially on the idea that tests ought to be written first. This is an ideal that I strive for, however, I have a tendency to write the unit tests afterwards.

Some people learn better by example. This article, rather than going in to great length about the principles of test driven development, will walk the reader through the process of building and testing an algorithm by writing the tests first, then changing the method being tested so that it fulfils the tests.

The final code and all the unit tests can be found in the accompanying download. This will require NUnit and Visual Studio 2005.

The specimen problem

I once saw a demo of how to create unit tests up front for a simple method. The method took a positive integer and turned it into roman numerals. So, I’m going to do something similar. I’m going to take an integer and turn it into words, in English. The rules for this may change depending on the language, so if English is not your only language, you may like to try to repeat this exercise in another language.

So, if the integer is 1, the result will be "one". If the integer is 23 the result will be "twenty three" and so on. Also note, I’ll be using British or Commonwealth English. So, for 101 the result in words is "one hundred and one". In American English it would be "one hundred one"

The walk through

The algorithm will also be refined through refactoring techniques. Agile development methodologies, especially eXtreme Programming, suggests that you do the simplest thing possible to get the thing working. So, going by this premise, I’ll work on the solution in bits. First, get it to return "one", then "one" or "two" depending on the input, and so on. Once 21 is reached it should become obvious where some refactoring can take place and so on. The final solution will work for 32 bit integers only.

Getting Started

Visual Studio 2005 has some features that can help with writing the tests first. A test can be written that calls into the class under test and the smart tags will prompt you with an offer to create the message stub for you.

The stub looks like this:

public static string NumberToEnglish(int p)
{
  throw new Exception("The method or operation is not implemented.");
}

If the test is completed to look like this:

[Test]
public void NumberToEnglishShouldReturnOne()
{
  string actual = English.NumberToEnglish(1);
  Assert.AreEqual("one", actual, "Expected the result to be "one"");
}

The test should fail because the stub throws an exception, rather than do what the test expects.

NUnit reports the error like this: "NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnOne : System.Exception : The method or operation is not implemented.".

The next thing to do is to ensure that the code satisfies the demands of the unit test. Agile methodologies, such as XP, say that only the simplest change should be made to satisfy the current requirements. In that case the method being tested will be changed to look like this:

public static string NumberToEnglish(int number)
{
  return "one";
}

At this point the unit tests are re-run and they all work out.

Test "two"

Since the overall requirement is that any integer should be translatable into words, the next test should test that 2 can be translated. The test looks like this:

[Test]
public void NumberToEnglishShouldReturnTwo()
{
  string actual = English.NumberToEnglish(2);
  Assert.AreEqual("two", actual, "Expected the result to be "two"");
}

However, since the method being tested returns "one" regardless of input at this point the test fails:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnTwo :
Expected the result to be "two"
	String lengths are both 3.
	Strings differ at index 0.
	expected: <"two">
	 but was: <"one">
	------------^

Again, keeping with the simplest change principle the code is updated to look like this:

public static string NumberToEnglish(int number)
{
  if (number == 1)
    return "one";
  else
    return "two";
}

The tests now pass.

Test "three" to "twenty"

A third test can now be written. It tests for an input of 3 and an expected return of "three". Naturally, at this point, the test fails. The code is updated again and now looks like this:

public static string NumberToEnglish(int number)
{
  switch (number)
  {
    case 1:
      return "one";
    case 2:
      return "two";
    default:
      return "three";
  }
}

To cut things short the new tests and counter-updates continue like this until the numbers 1 to 20 can be handled. The code will eventually look like this:

public static string NumberToEnglish(int number)
{
  switch (number)
  {
    case 1:
      return "one";
    case 2:
      return "two";
    case 3:
      return "three";
    case 4:
      return "four";
    case 5:
      return "five";
    case 6:
      return "six";
    case 7:
      return "seven";
    case 8:
      return "eight";
    case 9:
      return "nine";
    case 10:
      return "ten";
    case 11:
      return "eleven";
    case 12:
      return "twelve";
    case 13:
      return "thirteen";
    case 14:
      return "fourteen";
    case 15:
      return "fifteen";
    case 16:
      return "sixteen";
    case 17:
      return "seventeen";
    case 18:
      return "eighteen";
    case 19:
      return "nineteen";
    default:
      return "twenty";
  }
}

Test "twenty one" to "twenty nine"

At this point it looks like it will be pretty easy to do 21, but a pattern is about to emerge. After the tests for 21 and 22 have been written, the code is refactored to look like this:

public static string NumberToEnglish(int number)
{
  if (number < 20)
    return TranslateOneToNineteen(number);
  if (number == 20)
    return "twenty";
  return string.Concat("twenty ", TranslateOneToNineteen(number - 20));
}

private static string TranslateOneToNineteen(int number)
{
  switch (number)
  {
    case 1:
      return "one";
    case 2:
      return "two";
    case 3:
      return "three";
    case 4:
      return "four";
    case 5:
      return "five";
    case 6:
      return "six";
    case 7:
      return "seven";
    case 8:
      return "eight";
    case 9:
      return "nine";
    case 10:
      return "ten";
    case 11:
      return "eleven";
    case 12:
      return "twelve";
    case 13:
      return "thirteen";
    case 14:
      return "fourteen";
    case 15:
      return "fifteen";
    case 16:
      return "sixteen";
    case 17:
      return "seventeen";
    case 18:
      return "eighteen";
    default:
      return "nineteen";
  }
}

Now all the tests from 1 to 22 pass. 23 to 29 can be assumed to work because it is using well tested logic.

Test "thirty" to "thirty nine"

30 is a different story. The test will fail like this:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnThirty :
Expected the result to be "thirty"
	String lengths differ.  Expected length=6, but was length=10.
	Strings differ at index 1.
	expected: <"thirty">
	 but was: <"twenty ten">
	-------------^

By using the principle of doing the simplest thing that will work. The public method changes to:

public static string NumberToEnglish(int number)
{
  if (number < 20)
    return TranslateOneToNineteen(number);
  if (number == 20)
    return "twenty";
  if (number <= 29)
    return string.Concat("twenty ", TranslateOneToNineteen(number - 20));
  return "thirty";
}

Naturally, the test for 31 will fail:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnThirtyOne :
Expected the result to be "thirty one"
	String lengths differ.  Expected length=10, but was length=6.
	Strings differ at index 6.
	expected: <"thirty one">
	 but was: <"thirty">
	------------------^

So the code is changed again. This time to:

public static string NumberToEnglish(int number)
{
  if (number < 20)
    return TranslateOneToNineteen(number);
  if (number == 20)
    return "twenty";
  if (number <= 29)
    return string.Concat("twenty ", TranslateOneToNineteen(number - 20));
  if (number == 30)
    return "thirty";
  return string.Concat("thirty ", TranslateOneToNineteen(number - 30));
}

Test "forty" to "ninety nine"

A test for 40 will fail:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnForty :
Expected the result to be "forty"
	String lengths differ.  Expected length=5, but was length=10.
	Strings differ at index 0.
	expected: <"forty">
	 but was: <"thirty ten">
	------------^

The necessary code change starts to draw out a pattern. Of course, the pattern could have been quite easily predicted, but since this code is being built by the simplest change only rule, the pattern has to emerge before it can be acted upon.

The pattern repeats itself until it gets to 99. By this point the public method looks like this:

public static string NumberToEnglish(int number)
{
  if (number < 20)
    return TranslateOneToNineteen(number);
  int units = number % 10;
  int tens = number / 10;
  string result = "";
  switch (tens)
  {
    case 2:
      result = "twenty";
      break;
    case 3:
      result = "thirty";
      break;
    case 4:
      result = "forty";
      break;
    case 5:
      result = "fifty";
      break;
    case 6:
      result = "sixty";
      break;
    case 7:
      result = "seventy";
      break;
    case 8:
      result = "eighty";
      break;
    default:
      result = "ninety";
      break;
  }
  if (units != 0)
    result = string.Concat(result, " ", TranslateOneToNineteen(units));
  return result;
}

Test "one hundred"

The test for 100 will fail. The failure message is:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnOneHundred :
Expected the result to be "one hundred"
	String lengths differ.  Expected length=11, but was length=6.
	Strings differ at index 0.
	expected: <"one hundred">
	 but was: <"ninety">
	------------^

A quick change to the public method allows the test to pass:

public static string NumberToEnglish(int number)
{
  if (number == 100)
    return "one hundred";

  if (number < 20)
    return TranslateOneToNineteen(number);
  // Remainder omitted for brevity
}

Test "one hundred and one" to "one hundred and ninety nine"

What about 101? That test fails like this:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnOneHundredAndOne :
Expected the result to be "one hundred and one"
	String lengths differ.  Expected length=19, but was length=10.
	Strings differ at index 0.
	expected: <"one hundred and one">
	 but was: <"ninety one">
	------------^

At this point it should be easy to see that some of the work that has been done previously can be re-used with a small amount of refactoring. First refactor most of the body of the public method into a class called TranslateOneToNinetyNine. Then re-test to ensure that the refactoring process hasn’t introduced any new problems.

In Visual Studio 2005 it is very easy to highlight some code and extract it into a new method, thus allowing it to be reused by being called from multiple places.

Now the public method looks like the following and all previously successful tests continue to be successful

public static string NumberToEnglish(int number)
{
  if (number == 100)
    return "one hundred";

  return TranslateOneToNinetyNine(number);
}

For numbers from 101 to 199 the pattern is "one hundred and X" where X is the result of the translation between 1 and 99. Because it would take too long to write all those tests, it is possible to write just the edge cases and one or two samples from the middle of the range. That should give enough confidence to continue onwards. In this case, the tests are for 101, 115, 155 and 199.

The code is then re-written to support those tests:

public static string NumberToEnglish(int number)
{
  if (number < 100)
    return TranslateOneToNinetyNine(number);
  if (number == 100)
    return "one hundred";

  string result = string.Concat("one hundred and ",
    TranslateOneToNinetyNine(number - 100));

  return result;
}

Test "two hundred"

The next test to write is for 200. Naturally, this test will fail at this point as the code doesn’t support it. The test looks like this:

[Test]
public void NumberToEnglishShouldReturnTwoHundred()
{
    string actual = English.NumberToEnglish(200);
    Assert.AreEqual("two hundred", actual, "Expected the result to be "two hundred"");
}

The failing test can be predicted. It looks like this:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnTwoHundred :
Expected the result to be "two hundred"
	String lengths differ.  Expected length=11, but was length=22.
	Strings differ at index 0.
	expected: <"two hundred">
	 but was: <"one hundred and ninety">
	------------^

A simple change to the method can get the test passing:

public static string NumberToEnglish(int number)
{
    if (number < 100)
        return TranslateOneToNinetyNine(number);
    if (number == 100)
        return "one hundred";
    if (number == 200)
        return "two hundred";

    string result = string.Concat("one hundred and ",
        TranslateOneToNinetyNine(number - 100));

    return result;
}

Test "two hundred and one" to "two hundred and ninety nine"

Since the next part of the pattern can be seen as very similar to the one hundreds, the two edge cases and a couple of internal cases for the two hundreds are created. Presently, all those tests fail as the method has not been updated to take account of that range of integers.

In order to get those tests working the code is refactored like this:

public static string NumberToEnglish(int number)
{
    if (number < 100)
        return TranslateOneToNinetyNine(number);
    if (number == 100)
        return "one hundred";
    if (number < 200)
        return string.Concat("one hundred and ",
        TranslateOneToNinetyNine(number - 100));
    if (number == 200)
        return "two hundred";

    return string.Concat("two hundred and ",
        TranslateOneToNinetyNine(number - 200));
}

Test "three hundred" to "nine hundred and ninety nine"

From the last change to the method a pattern can be seen to be emerging. The code for dealing with the one hundreds and two hundreds are almost identical. This can be easily changed so that all positive integers between 1 and 999 can be converted into words.

After various unit tests are written to test values from 300 to 999 the code is changed to this:

public static string NumberToEnglish(int number)
{
    if (number < 100)
        return TranslateOneToNinetyNine(number);
    int hundreds = number / 100;
    string result = string.Concat(TranslateOneToNineteen(hundreds),
        " hundred");
    int remainder = number % 100;
    if (remainder == 0)
        return result;

    return string.Concat(result, " and ", TranslateOneToNinetyNine(remainder));
}

Test "one thousand"

As before, the first thing to do is write the test:

[Test]
public void NumberToEnglishShouldReturnOneThousand()
{
    string actual = English.NumberToEnglish(1000);
    Assert.AreEqual("one thousand", actual, "Expected the result to be "one thousand"");
}

Which fails:

NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnOneThousand :
Expected the result to be "one thousand"
	String lengths differ.  Expected length=12, but was length=11.
	Strings differ at index 0.
	expected: <"one thousand">
	 but was: <"ten hundred">
	------------^

And the fix:

public static string NumberToEnglish(int number)
{
    if (number == 1000)
        return "one thousand";

    if (number < 100)
        return TranslateOneToNinetyNine(number);
    int hundreds = number / 100;
    string result = string.Concat(TranslateOneToNineteen(hundreds),
        " hundred");
    int remainder = number % 100;
    if (remainder == 0)
        return result;

    return string.Concat(result, " and ", TranslateOneToNinetyNine(remainder));
}

Test "one thousand and one" to "nine thousand nine hundred and ninety nine"

Some forward thinking will reveal that the logic will be similar for the thousands as it was for the hundreds. So, rather than repeat all that in this article, the steps to refactoring the code to work with the range from 101 to 999 can be used similarly with 1001 to 9999. The accompanying download will show all the unit tests.

The final result of this stage is that the public method has been refactored to this:

public static string NumberToEnglish(int number)
{
    if (number < 1000)
        return TranslateOneToNineHundredAndNinetyNine(number);

    int thousands = number / 1000;
    string result = string.Concat(TranslateOneToNineteen(thousands),
        " thousand");
    int remainder = number % 1000;
    if (remainder == 0)
        return result;

    if (remainder < 100)
        return string.Concat(result, " and ",
            TranslateOneToNinetyNine(remainder));

    return string.Concat(result, " ",
        TranslateOneToNineHundredAndNinetyNine(remainder));
}

private static string TranslateOneToNineHundredAndNinetyNine(int number)
{
    if (number < 100)
        return TranslateOneToNinetyNine(number);
    int hundreds = number / 100;
    string result = string.Concat(TranslateOneToNineteen(hundreds),
        " hundred");
    int remainder = number % 100;
    if (remainder == 0)
        return result;

    return string.Concat(result, " and ", TranslateOneToNinetyNine(remainder));
}

Test "ten thousand" to "nine hundred and ninety nine thousand nine hundred and ninety nine"

In the first set of test, that were expected to fail, for the condition that the integer input was a value greater than 9999 actually shows passing tests. This serendipitous circumstance is caused by the TranslateOneToNineteen method being a compatible match for prefixing the "thousand" for a range up to the 19 thousands. Through this code reuse it is possible to get a full range match all the way up to 999999 with only a change to a part of one line of code.

The public method has now changed to:

public static string NumberToEnglish(int number)
{
    if (number < 1000)
        return TranslateOneToNineHundredAndNinetyNine(number);

    int thousands = number / 1000;
    string result = string.Concat(TranslateOneToNineHundredAndNinetyNine(thousands),
        " thousand");
    int remainder = number % 1000;
    if (remainder == 0)
        return result;

    if (remainder < 100)
        return string.Concat(result, " and ",
            TranslateOneToNinetyNine(remainder));

    return string.Concat(result, " ",
        TranslateOneToNineHundredAndNinetyNine(remainder));
}

Test "one million" to "nine hundred and ninety nine million nine hundred and ninety nine thousand nine hundred and ninety nine"

The way the code changes as the number of digits increases should becoming more apparent by now. The amount of code reuse is increasing. The number of necessary tests is decreasing. Confidence is increasing

At the start the first 20 numbers each had their own test. 100% of inputs had a test. From 20 to 99 it was 20 tests. Only 25% of the inputs had tests. From 100 to 999 there were 18 tests. Just 2% of the inputs had tests. From 1000 to 999999 there were, again, just 18 tests. This represents just 2 thousandths of one percent.

At this point the public method has been refactored to look like this:

public class English
{
public static string NumberToEnglish(int number)
{
    if (number < 1000000)
        return TranslateOneToNineHundredAndNinetyNineThousandNineHundredAndNinetyNine(number);

    int millions = number / 1000000;
    string result = string.Concat(TranslateOneToNineHundredAndNinetyNine(millions),
        " million");
    int remainder = number % 1000000;
    if (remainder == 0)
        return result;

    if (remainder < 100)
        return string.Concat(result, " and ",
            TranslateOneToNinetyNine(remainder));

    return string.Concat(result, " ",
        TranslateOneToNineHundredAndNinetyNineThousandNineHundredAndNinetyNine(remainder));
}

private static string TranslateOneToNineHundredAndNinetyNineThousandNineHundredAndNinetyNine(int number)
{
    if (number < 1000)
        return TranslateOneToNineHundredAndNinetyNine(number);

    int thousands = number / 1000;
    string result = string.Concat(TranslateOneToNineHundredAndNinetyNine(thousands),
        " thousand");
    int remainder = number % 1000;
    if (remainder == 0)
        return result;

    if (remainder < 100)
        return string.Concat(result, " and ",
            TranslateOneToNinetyNine(remainder));

    return string.Concat(result, " ",
        TranslateOneToNineHundredAndNinetyNine(remainder));
}

Test "one billion" upwards

The limitations of an integer (Int32) mean that this section reaches the upper limits of 2147483647. Unless an Int64 is used there is no continuation to the trillion range.

Final stages

To this point all positive integers are successfully being translated from an integer into a string of words. At this point, through code reuse, it should be a fairly simple matter to refactor the code to work with negative numbers and zero.

Zero is easy enough. The unit test is put in place:

[Test]
public void NumberToEnglishShouldReturnZero()
{
  string actual = English.NumberToEnglish(0);
  Assert.AreEqual("zero", actual, "Expected the result to be "zero"");
}

And it promptly fails because there is no code to support it. The public method is changed so that it does a quick check at the start:

public static string NumberToEnglish(int number)
{
  if (number == 0)
      return "zero";
  if (number < 1000000000)
      return TranslateOneToNineHundredAndNintyNineMillion...(number);

  int billions = number / 1000000000;
  string result = string.Concat(TranslateOneToNineteen(billions), " billion");

  int remainder = number % 1000000000;
  if (remainder == 0)
    return result;

  if (remainder < 100)
    return string.Concat(result, " and ", TranslateOneToNinetyNine(remainder));

  return string.Concat(result, " ",
    TranslateOneToNineHundredAndNintyNineMillion...(remainder));
}

Now the test passes. Next is to permit negative numbers.

[Test]
public void NumberToEnglishShouldReturnNegativeOne()
{
  string actual = English.NumberToEnglish(-1);
  Assert.AreEqual("negative one", actual, "Expected the result to be "negative one"");
}

This fails so the code is refactored to this:

public static string NumberToEnglish(int number)
{
  if (number == 0)
    return "zero";

  string result = "";
  if (number < 0)
    result = "negative ";

  int absNumber = Math.Abs(number);

  return string.Concat(result,
    TranslateOneToTwoBillion...SixHundredAndFortySeven(absNumber));
  // Method call above contracted for brevity
}

And the test passes. But what about that final edge case? int.MinValue? The test is written but it fails. The reason is thatMath.Abs(int.MinValue) isn’t possible. So, as this is a one off case, the easiest solution is to put in a special case into the public method:

// Special case for int.MinValue.
if (number == int.MinValue)
  return "negative two billion one hundred and forty seven million " +
    "four hundred and eighty three thousand six hundred and forty eight";

Conclusion

This article demonstrates how to unit test and build a piece of code in small increments. The tests continually prove that the developer is on the right path. As the code is built the constant rerunning of existing tests prove that any new enhancements do not break existing code. If, for any reason, it is later found that the code contains a bug, a test can easily be created that exercises that incorrect code and a fix produced.

The full final code is available in the associated download along with a set of NUnit tests.

Downloads

You can download the example code for this article here.

How to get a list of all subdirectories

This is an example of how to obtain a list of all subdirectories using a recursive method with the .NET Framework.

public static List GetSubdirectories(DirectoryInfo directory)
{
    // Set up the result of the method.
    List<DirectoryInfo> result = new List<DirectoryInfo>();

    // Attempt to get a list of immediate child directories from the directory
    // that was passed in to the method.
    DirectoryInfo[] childDirectories;
    try
    {
        childDirectories = directory.GetDirectories();
    }
    catch (UnauthorizedAccessException uae)
    {
        // If the permissions do not authorise access to the contents of the
        // directory then return an empty list.
        return result;
    }

    // Loop over all the child directories to get their contents.
    foreach (DirectoryInfo childDirectory in childDirectories)
    {
        // Add the child directory to the result list
        result.Add(childDirectory);

        // Get any children of the current child directory
        List<DirectoryInfo> grandchildDirectories = GetSubdirectories(childDirectory);

        // Add the child's children (the grandchildren) to the result list.
        result.AddRange(grandchildDirectories);
    }

    // return the full list of all subdirectories of the one passed in.
    return result;
}

The code requires the following namespaces:

  • System.Collections.Generic
  • System.IO
  • System.Diagnostics

Passing Values Between Forms in .NET

Introduction

I wrote this article in response to an almost overwhelming number of requests on forums on how to pass a variable from a one Windows Form to another. In fact, saying that it is going between one form and another is somewhat of a misnomer because this will work for any type of object not just Forms. This seems to be one area where beginners in C# and VB.NET often get stuck. So, rather than having to repeat myself often in forums I wrote this article so that I could point people at it so that they will have the benefit of a full explanation as well as the answer to their problem.

The code examples that come with this article are available for VB.NET and C# so that neither group feels left out. If you develop software in any of the other languages available for .NET then you can probably follow on too. The techniques are the same for all .NET languages the only difference should be in the language syntax.

Parent to child

Passing a value from a parent to a child class is hopefully one of the easiest techniques and is the one I’ll start with. The idea is simple. The parent class needs to pass some value to the child class. In this example, I have set up a simple parent form with a TextBox control where the user can type any value they like, then they can open the child form and see that value appear there.

First of all, the child class needs some way to receive the value from the parent. I’ve set up a property to receive the value and it will set the Text value of a TextBox on the child form. In reality this could set a field value or get passed to another object and so on.

C#
public string ValueFromParent
{
    set
    {
        this.uxParentValue.Text = value;
    }
}
VB.NET
Public WriteOnly Property ValueFromParent() As String
    Set(ByVal Value As String)
        Me.uxParentValue.Text = Value
    End Set
End Property

Passing the value on construction

To make the initialization of the class easier, the constructor will take a parameter which will be the current value to be passed. The constructor uses the property so that the code can be reused. Admittedly, in this example there is only one line in the property, but as an element of future proofing it means that there is the possibility of adding more functionality to the property in future should it need. That additional functionality will be implemented without having to change a lot of existing code.

C#
public ChildForm(string initialValue)
{
    InitializeComponent();
    ValueFromParent = initialValue;
}
VB.NET
Public Sub New(ByVal initialValue As String)
    MyBase.New()
    'This call is required by the Windows Form Designer.
    InitializeComponent()
    ValueFromParent = initialValue
End Sub

Now, in order for the parent to pass the value to the child, it only has to set the property. For example, when using the child form as a dialog the value from the parent can be passed as follows:

C#
private void uxOpenDialog_Click(object sender, System.EventArgs e)
{
    // Get the value to be passed
    string parentValue = this.uxUserResponse.Text;
    // Create the child form.
    ChildForm child = new ChildForm(parentValue);
    // Show the form which will display the user's value.
    child.ShowDialog();
}
VB.NET
Private Sub uxOpenDialog_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles uxOpenDialog.Click
    ' Get the value that the child will be initialised with
    Dim initialValue As String
    initialValue = Me.uxUserResponse.Text
    Dim childForm As ChildForm
    ' Create the child form.
    childForm = New ChildForm(initialValue)
    ' Show the child dialog.
    childForm.ShowDialog()
End Sub

Passing the value while the form is open

Of course, it may be necessary to pass a value when the child form is already open. This is also possible if the parent form stores a reference to the child form and then uses that to pass updates to the child form using the property in the child form that was set up earlier.

In my example, the parent is going to store a reference to the child as a field in the ParentForm class like this:

C#
private ChildForm uxChildForm;
VB.NET
Private uxChildForm As ChildForm

When creating the child form it is therefore important to pass the reference to the child form into the field variable. For example:

C#
private void uxOpenForm_Click(object sender, System.EventArgs e)
{
    this.uxChildForm = new ChildForm();
    this.uxChildForm.ValueFromParent = this.uxUserResponse.Text;
    this.uxChildForm.Show();
}
VB.NET
Private Sub uxOpenForm_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles uxOpenForm.Click
    Me.uxChildForm = New ChildForm
    Me.uxChildForm.ValueFromParent = Me.uxUserResponse.Text
    Me.uxChildForm.Show()
End Sub

Finally, whenever the parent needs to tell the child that the value is updated it can do so just by passing the new value to the property that was set up in the child form. For example:

C#
private void uxUserResponse_TextChanged(object sender, System.EventArgs e)
{
    if (this.uxChildForm != null)
    {
        this.uxChildForm.ValueFromParent = this.uxUserResponse.Text;
    }
}
VB.NET
Private Sub uxUserResponse_TextChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles uxUserResponse.TextChanged
    If Not Me.uxChildForm Is Nothing Then
        Me.uxChildForm.ValueFromParent = Me.uxUserResponse.Text
    End If
End Sub

The code for this is in the zip file above. The projects are ParentToChildCS (for C# developers) and ParentToChildVB (for VB developers).

Sibling to Sibling

The next most common request seems to be passing a value between two siblings. That is, two child classes sharing the same parent class. This also demonstrates passing between the child and the parent.

First, it is important to note that in most cases the two child classes should probably know nothing about each other. If the two child classes start to communicate directly with each other the coupling in the application increases and this will make maintenance of the application more difficult. Therefore the first thing to do is to allow the child classes to raise events when they change.

In order to raise events, create a delegate to define the signature of the method that will be called when the event is raised. It is a good practice to conform to the same style as the delegates used in the .NET Framework itself. For example, if an event handler for the Click event of a Button is created then it is possible to see that the signature of the method created by the IDE has two parameters, sender and e. sender is an object and is a reference to the object that generated the event. e is the EventArgs (or a something derived from EventArgs).

With that in mind, the delegate created here will have sender and e parameters as well. But for the e parameter a new class will be created to store the specific details of the event.

C#
public class ValueUpdatedEventArgs : System.EventArgs
{
    // Stores the new value.
    private string newValue;
    // Create a new instance of the
    // ValueUpdatedEventArgs class.
    // newValue represents the change to the value.
    public ValueUpdatedEventArgs(string newValue)
    {
        this.newValue = newValue;
    }
    // Gets the updated value.
    public string NewValue
    {
        get
        {
            return this.newValue;
        }
    }
}
VB.NET
Public Class ValueUpdatedEventArgs
    Inherits System.EventArgs
    ' Stores the new value
    Dim _newValue As String
    ' Create a new instance of the
    ' ValueUpdatedEventArgs class.
    ' newValue represents the change to the value.
    Public Sub New(ByVal newValue As String)
        MyBase.New()
        Me._newValue = newValue
    End Sub
    ' Gets the updated value
    ReadOnly Property NewValue() As String
    Get
        Return Me._newValue
    End Get
    End Property
End Class

Next the delegate needs to be defined.

C#
public delegate void ValueUpdated(object sender,
    ValueUpdatedEventArgs e);
VB.NET
Public Delegate Sub ValueUpdated(ByVal sender As Object, _
    ByVal e As ValueUpdatedEventArgs)

Now that the foundation of the mechanism for informing other objects of changes is written, the child classes can implement the raising of events so that observers (i.e. interested parties) can be notified when the value changes.

In the class for the child forms the event ValueUpdated is declared so that interested parties can indicate what they want to observe.

C#
public event ValueUpdated ValueUpdated;

This is one area where C# and VB.NET differ. In C# an event requires a delegate, whereas in VB.NET the signature of the method to be called needs to be declared as part of the event. The advantage for C# is that the delegate only has to be declared once and it can be reused in many places whereas VB.NET has to have essentially the same bit of code, the method signature, rewritten frequently – this can be an area where there can be discrepancies between one class and another.

Next, when the child class is updated it needs to inform its observers (the interested parties, in this case it will be the parent and sibling forms). The following code shows what happens when the text is changed on the form.

C#
private void uxMyValue_TextChanged(object sender, System.EventArgs e)
{
    // Get the new value from the text box
    string newValue = this.uxMyValue.Text;
    // Create the event args object.
    ValueUpdatedEventArgs valueArgs =
    new ValueUpdatedEventArgs(newValue);
    // Inform the observers.
    ValueUpdated(this, valueArgs);
}
VB.NET
Private Sub uxMyValue_TextChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles uxMyValue.TextChanged
    Dim newValue As String
    newValue = Me.uxMyValue.Text
    Dim valueArgs As ValueUpdatedEventArgs
    valueArgs = New ValueUpdatedEventArgs(newValue)
    RaiseEvent ValueUpdated(Me, valueArgs)
End Sub

Now that the child form can inform others of the changes and what the changes are, the parent needs to open the child form and register as an observer so that it can be informed when changes are made. The parent will also ensure that other siblings that are interested get added as observers too.

C#
private void uxOpenChildA_Click(object sender, System.EventArgs e)
{
    // Create the child form
    this.childA = new ChildAForm();
    // Add an event so that the parent form is informed when the child
    // is updated.
    this.childA.ValueUpdated += new ValueUpdated(childA_ValueUpdated);
    // Add an event to each child form so that they are notified of each
    // others changes.
    if (this.childB != null)
    {
        this.childA.ValueUpdated +=
            new ValueUpdated(this.childB.childA_ValueUpdated);
        this.childB.ValueUpdated +=
            new ValueUpdated(this.childA.childB_ValueUpdated);
    }
    this.childA.Show();
}
VB.NET
Private Sub uxOpenChildA_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles uxOpenChildA.Click
    ' Create the child form
    Me.childA = New ChildAForm
    ' Add a handler to this class for when child A is updated
    AddHandler childA.ValueUpdated, AddressOf ChildAValueUpdated
    If Not Me.childB Is Nothing Then
    ' Make sure that the siblings are informed of each other.
        AddHandler childA.ValueUpdated, _
            AddressOf childB.ChildAValueUpdated
        AddHandler childB.ValueUpdated, _
            AddressOf childA.ChildBValueUpdated
    End If
    ' Show the form
    Me.childA.Show()
End Sub

All that remains is to implement the event handlers.

C#
private void childA_ValueUpdated(object sender, ValueUpdatedEventArgs e)
{
    // Update the text box on this form (the parent) with the new
    /// value from the child
    this.uxChildAValue.Text = e.NewValue;
}
VB.NET
Private Sub ChildAValueUpdated(ByVal sender As Object, _
    ByVal e As ValueUpdatedEventArgs) Handles childA.ValueUpdated
    ' Update the value on this form (the parent) with the
    ' value from the child.
    Me.uxChildAValue.Text = e.NewValue
End Sub

And similarly in the child class.

C#
public void childB_ValueUpdated(object sender, ValueUpdatedEventArgs e)
{
    // Update the text box on this form (child A) with the new value
    this.uxOtherValue.Text = e.NewValue;
}
VB.NET
Public Sub ChildBValueUpdated(ByVal sender As Object, _
    ByVal e As ValueUpdatedEventArgs)
    Me.uxOtherValue.Text = e.NewValue
End Sub

The code for this example is in the accompanying zip file. The project is called SiblingToSiblingCS (for the C# version) and SiblingToSiblinVB (for the VB.NET version)

Conclusion

It is quite simple to pass values from one object to another. In some instances it does take a little bit of effort to get it done right. Especially as it is all too easy to couple forms together that really shouldn’t know about each other.

©2005 Colin Angus Mackay. All Rights Reserved – The only authorized websites that may show this article are CodeProject, ColinMackay.co.uk and Developer fusion.