December 2006 - Posts

I blogged about Sandcastle in the past, over here. You can grab the December 06 CTP from the Microsoft-website now. Take a look at the Sandcastle MSDN Blog too.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

A few days ago I blogged about extension methods in C# 3.0 as a piece of glue to support LINQ (although it's not strictly required to enable LINQ, it's the most natural way to "extend" existing collections etc with query operators and allow a pretty straightforward translation between query operator syntax and chained extension method calls as an intermediate compilation step).

Somewhat later I got the following question from a reader of mine, John Rusk:

Bart,

What do you think about the possible versioing problems with extension methods? I blogged about it here, http://dotnet.agilekiwi.com/blog/2006/04/extension-methods-problem.html . Everyone is is talking about segregating extension methods into their own namespaces, but I'm not sure that completely solves the problem.

In this post I'd like to discuss the problem mentioned on the following pages which John is referring to:

Warning: The ideas below are just some personal random thoughts that haven't been revised thoroughly; no guarantuees are made and none of the ideas below are a reflection of the C# team's ideas. The only official source for C# 3.0 language specification is the one you can find on the Microsoft website. All syntax propositions are imaginary and won't compile at all. I'm also sure to have overlooked various issues with the proposals being made, so don't start throwing rotten tomatoes at me :-). Suggestions and feedback are welcome (as usual) but it might be more advisable to direct your concerns to the C# team directly.

 

Problem statement

Basically there are different problems to be considered:

  1. You have defined an extension method Foo, for class Bar in library SomeLib version 1.0. In version 2.0 of SomeLib however there's an instance method called Foo on class Bar. When you recompile the code, the compiler will now favor the instance method instead of the extension method and behavior has changed.

    //v1.0
    namespace SomeLib
    {
       public class Bar
       {
       }
    }

    //Extension for v1.0
    public static class MyExtensions
    {
       public static void Foo(this SomeLib.Bar bar)
       {
          // #@*
       }
    }

    //v2.0
    namespace SomeLib
    {
       public class Bar
       {
          public void Foo()
          {
             //... (different behavior than #@*)
          }
       }
    }

    //usage
    using SomeLib;
    using
    MyExtensions;

    class
     Program
    {
       public static void Main()
       {
          //behavior will change when compiling against SomeLib v2.0
          Bar b = new Bar();
          b.Foo();
       }
    }

  2. Multiple namespace imports can introduce conflicts if both namespaces have an extension method with the same name defined for the same target type:

    //v1.0
    namespace SomeLib
    {
       public class Bar
       {
       }
    }
  3. //First set of extensions
    namespace Ext1
    {

       public static class
    MyExtensions
       {
          public static void Foo(this SomeLib.Bar bar)
          {
             // #@*
          }
       }

      
    //...
    }

    //Second set of extensions
    namespace Ext2
    {

       public static class
    MyExtensions
       {
          public static void Foo(this SomeLib.Bar bar)
          {
             // $ยต!
          }
       }

      
    //...
    }

    //usage
    using SomeLib;
    using
    Ext1;
    using Ext2;

    class
     Program
    {
       public static void Main()
       {
          //Which Foo will be called?
          Bar b = new Bar();
          b.Foo();
       }
    }

To summarize, the "minimality" of the current extension method implementation might be its major drawback too. It's basically built around an extended meaning for the using statement and an additional use case for the this keyword. Einstein's words might be applicable:

"Everything should be made as simple as possible, but not simpler."

 

A few thoughts

As the matter in fact, method resolution precedence is a double-edged sword in this problem. If instance methods take precedence on extension methods, problem 1 can occur. If the reverse were true, i.e. extension methods that take precedence on instance methods, adding a new using statement to the code can change behavior because some extension is brought in scope. A few remarks:

  • It's important to realize that behavior won't change without a recompilation: the IL code remains a static method call till the compiler comes around and recompiles the code with the choice for an instance method instead of a static method on a static class (the extension method). So, having a new version of a library installed on a machine doesn't change the behavior all of a sudden: the extension method will still be called instead of the newly available instance method in the new version of the library.
  • Recompilation can be the trigger to some intelligent analysis: if the method being called was an extension method (i.e. a static method call in IL) and now an instance method is available, it could transform the original extension method instance-method-call-style code into the equivalent static-method-on-static-class-call code to resolve the conflict. Nevertheless, this introduces additional analysis of the existing assembly which is a rather cumbersome idea at first glance.
  • The ultimate solution would be not to have precedence at all: if an instance method and an extension method are available, there's a conflict and one has to make its intention explicit: for extension method calls this would come down to using a classic static-method-on-static-class-call but for instance method calls things would be more difficult because of additional syntax required: ((string) s).Reverse() might be an explicit but "noise introducing" indication to use an instance method, not yet taking possible subtleties with virtual method calls etc in consideration.

Another question one might ask is whether or not the use of using as the "extension methods importing operator" is the good choice. By doing so, using has a three-way semantic, i.e. importing namespaces, importing extensions through namespaces and working with IDisposable objects. This can introduce the side effect that importing a namespace (for convenience use of certain types, i.e. "abbreviating long names") also imports extension methods. A few remarks:

  • You might desire more fine-grained control, e.g. by writing stuff like using MyNamespace.TheStaticClassWithExtensions. As an example, one would replace using System.Query by using System.Query.Sequence. Obviously, the name choice for the static class is key to readability of the consumer code.
  • It's a good idea to segregate extension methods into a separate namespace which is exclusively used for extension methods. The compiler might enforce this rule. However, one might like to add other classes (static or not) to the same namespace as "helpers" to provide the functionality; additional rules for existence of those classes would be required: these might be nested or declared as internal or ...
  • A separate statement to import extension methods might be more expressive to indicate the use of extensions. It'd make the compiler's live a little easier by having an explicit list of "extension method sources". Possibilities include using extensions ... (too long?) or extend from ... (from is a token already) or extend with ... or whatever else.

What about multiple extension sources available for the same type? For example: namespace Bar contains an extension method called Reverse for System.String, whileas namespace Foo does the same. Namespace segregation might help but not eliminate all possible problems. Again, more fine-grained control might be desirable.

  • The last bullet from the previous paragraph could be taken a little step further, again introducing more control but more writing as well: extend <target type> with <extension type>. For example: extend System.String with Bar.StringExtension where StringExtension is the static class with extension methods.
  • This idea would be optimal when extension methods are made more explicit concerning type-based separation. For example, you might want to extend type System.String, which you might do in a separate "extension class" for that type: class StringExtension extends System.String. It's not inheritance (the : operator) but might be confusing compared to Java concerning keyword choice. It eliminates the need to use the this keyword on the first parameter, because extensions are now on a type-by-type basis: public string Reverse() { // use 'this' somewhere }. Therefore, the this keyword can be used as if you would be really inside the target type itself, except for that it only exposes public members. If you ever get the chance to change the target type itself, you could simply copy-paste the code written in the extension method to the target type's definition. The question that remains: where are static modifiers required for "clarity" (this and static are quite orthogonal)? Let's just leave the static modifiers in place for the sample below.
  • One might argue that with this level of fine-grained control, extension methods could take precedence under all circumstances: if you don't like a particular extension, you could just fall back on the old-style static method calls where you need the extensions. By doing this, extension methods hide instance methods; syntax coloring might indicate the use of extension methods.

 

Some random ideas

An example would be this:

using System;

namespace Bar
{
   public static class StringExtensions extends String // or public extension class StringExtensions : String
   {
      public static string Reverse()
      {
         char[] c = this.ToCharArray();
         Array.Reverse(c);
         return new string(c);
      }
   }
}

namespace Foo
{
   extend String with Bar.StringExtensions;

   class Program
   {
      public static void Main()
      {
         string s = "Hello world";
         Console.WriteLine(s.Reverse());
      }
   }  
}

Pros:

  • Versioning problem solved because extension methods take precedence (i.e. hide) over instance methods. Fine-grained control over the extension imports can be used as an argument for this principle. Explicit instance member call syntax isn't available; in such a case one has to remove the extend ... with ... statement.
    • Note: extend ... with ... could be extended even further to allow extension imports on a method-per-method basis or with 'except for' lists to reduce a conflict (heavy!):
      • extend <target type> with <extension class>
      • extend <target type> with <extension class>.<extension method>
        - or - extend <target type> with <extension method comma-separated list> in <extension class>
        - or - extend <target type> with <extension class> methods <extension method comma-separated list>
      • extend <target type> with <extension class> excluding <extension method comma-separated list>
        - or - extend <target type> with <extension class> methods excluding <extension method comma-separated list>
    • Samples:
      • extend String with Bar.StringExtensions;
      • extend String with Bar.StringExtensions.Reverse;
        extend String with Reverse in Bar.StringExtensions;
        extend String with Bar.StringExtensions methods Reverse;
      • extend String with Bar.StringExtensions excluding TrimEnd; //extension class has defined TrimEnd but we want to use the instance method defined on System.String
        extend String with Bar.StringExtensions methods excluding TrimEnd;
  • Can deal with multiple extensions for the same class thanks to fine-grained "extension imports". Multiple extensions for the same type could be imported if these don't overlap with each other (i.e. meaning they have a method with the same signature in the intersection of extension methods).
  • Porting extension methods to instance methods is a matter of copy-paste if one has access to the target type's source code (e.g. in a later stage of a product's evolution when a target type itself can be extended with functionality).

Cons:

  • More complex than the original idea of extension methods, for the end user and the compiler. In the end, there's more (but more explicit) syntactical sugar involved.
    • Sample:

      using System.Query;

      becomes

      extend IEnumerable<T> with System.Query.Sequence;
  • Requires a separate extension class for each type extended (needed for fine-grained control).
  • An explicit static method call to an extension method is less intuitive because of the hidden parameter:
    • Sample:

      Calling

         public static class StringExtensions extends String
         {
            public static string Reverse()

      is done like this

         string reverse = StringExtensions.Reverse(somestring);
    • This shouldn't be a problem if you do
      • consider the extend ... with ... excluding ... syntax which can be used to reduce static method calls;
      • consider possible IntelliSense support in Visual Studio which shows the hidden parameter when making an explicit static method call;
      • compare it with the current situation where the "this <class> parameter" gets hidden when calling an extension method (read: things are just turned upside down).
    • Observe that compilation of the extension method itself is not so much more difficult: all occurences of this should be replaced by the (hidden) first parameter's value/reference.

The solution of John using contractual explicitness seems pretty nice too, but syntax looks quite awkward at first glance with the "method casting style":

s.(IContainable)Contains(t);

Nevertheless, it provides a good solution to the precedence and versioning-related problems aforementioned by allowing explicitness for target method call choise. However, on the definition side things look a little weird for the moment:

public static class Extender : IFooable
{
   public static void Foo(this Thing t)
   {
      //...
   }
}

public interface IFooable
{
   void Foo();
}

For example, interfaces are used for instance members and the static class "implements" IFooable. Also, looking at the interface in isolation, you can't see the correlation with the extension of the "Thing" class.

 

Conclusion

To summarize, I do understand the concerns of people like John with the current implementation of extension methods and I also do agree things need to be changed a bit to make its use safer and to eliminate possible versioning issues. In this post, I've put a light on those issues and proposed ideas for possible solutions, which might be a little 'dramatic' because of the 'makeover character' of these propositions. Less disruptive solutions might work out pretty well too, such as a more fine-grained control over which extension types (and/or methods) have to be imported. In the end, I'd like to say that extension methods should be used with care, like most language features, concerning the risky versioning business we're faced with when writing reusable libraries.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Anonymous and named pipes are IPC mechanisms to communicate between processes. Basically, anonymous pipes work only for communication between processes in a one-way fashion on the same machine, whileas named pipes can be used for two-way communication between a server and clients.

Personally, I've had some exposure to pipes in the past when reading about SQL Server Internals and experimenting with CreateNamedPipe, (Dis)ConnectNamedPipe, CallNamedPipe, amongst others. Pretty complex stuff but very powerful.

So, I'm happy to point you to the Introducing Pipes post on the BCL Team's blog which brings the good news that using pipes is now also in the managed code developer's toolkit! I hope to find some time to play with this myself in the very near future.

I'll blog about other Orcas features myself later on, such as the System.Threading.ReaderWriterLockSlim class I've been playing with a bit lately. If you haven't download the Orcas October CTP yet, download it here. It might be a little late to tell you this, since the change of having a new CTP available increases day by day :-).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Introduction

In this C# 3.0 Feature Focus Week we'll focus on the new language features that will be part of C# 3.0 "Orcas". As you already might know, the major innovation on Orcas is the LINQ (Language Integrated Query) technology that will make data queries a first class citizen of the language (C# 3.0 and VB 9.0). In order to unlock this potential, a set of language features were added to the language that all work in concert to enable LINQ stuff. However, all of those individual features prove to be useful in isolation as well. Later, we'll focus on LINQ itself.

 

Lambda Expressions

Time for yet another noise eliminating feature in C# 3.0, based on functional programming concepts (lambda calculus). Consider the following basic sample in which we want to have to some calculate function that takes three arguments, a function pointer (read: delegate) to a binary operation function (read: a method with signature int BinOp(int a, int b)) and two operandi, as a generic way to deal with binary operation calculations like addition, subtraction, multiplication, division, modulo, whatever you can think of. Defining this is piece of cake, using a simple delegate:

using System;

class Lambda
{
   delegate int BinOp(int a, int b);

   static void Main()
   {
   }

   static int Calculate(BinOp op, int a, int b)
   {
      return op(a,b);
   }
}

However, using it might be a bit more cumbersome. Here's what it'd look like in C# 1.0 (noise underlined):

using System;

class Lambda
{
   delegate int BinOp(int a, int b);

   static void Main()
   {
      int res = Calculate(Sum, 1, 2);

      Console.WriteLine(res);

   }

   static int Sum(int a, int b)
   {
      return a + b;
   }

   static int Calculate(BinOp op, int a, int b)
   {
      return op(a,b);
   }
}

In C# 2.0, the need for a separate method definition was eliminated using anonymous methods, yielding the following (cleaner?) syntax:

using System;

class Lambda
{
   delegate int BinOp(int a, int b);

   static void Main()
   {
      int res = Calculate(delegate (int a, int b) { return a + b; }, 1, 2);

      Console.WriteLine(res);

   }

   static int Calculate(BinOp op, int a, int b)
   {
      return op(a,b);
   }
}

In the end, we just want to express that two variables with dummy names a and b have to be transformed into a result that's the sum of both numbers, i.e. a+b. Lambda expressions allow us to do just this, as follows:

using System;

class Lambda
{
   delegate int BinOp(int a, int b);

   static void Main()
   {
      int res = Calculate((a,b) => a + b, 1, 2);

      Console.WriteLine(res);

   }

   static int Calculate(BinOp op, int a, int b)
   {
      return op(a,b);
   }
}

Notice we don't need to specify the types of a and b since the compiler can infer the types automatically. Behind the scenes, the compiler transforms the lambda expression in an anonymous method, which on its turn is transformed into a randomly named private method:

.method private hidebysig static int32 '<Main>b__0'(int32 a, int32 b) cil managed
{
   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
   .locals init (int32 V_0)
   IL_0000: nop
   IL_0001: ldarg.0
   IL_0002: ldarg.1
   IL_0003: add
   IL_0004: stloc.0
   IL_0005: br.s IL_0007
   IL_0007: ldloc.0
   IL_0008: ret
} // end of method Lambda::'<Main>b__0'

and a "cached anonymous delegate":

.field private static class Lambda/BinOp '<>9__CachedAnonymousMethodDelegate1'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )

Finally, Main creates a BinOp delegate object pointing to the anonymous method (IL_0009, IL_000f) and stores it in the cache anonymous delegate (IL_0014):

.method private hidebysig static void Main() cil managed
{
   .entrypoint
   .locals init (int32 V_0)
   IL_0000: nop
   IL_0001: ldsfld class Lambda/BinOp Lambda::'<>9__CachedAnonymousMethodDelegate1'
   IL_0006: brtrue.s IL_001b
   IL_0008: ldnull
   IL_0009: ldftn int32 Lambda::'<Main>b__0'(int32,int32)
   IL_000f: newobj instance void Lambda/BinOp::.ctor(object,native int)
   IL_0014: stsfld class Lambda/BinOp Lambda::'<>9__CachedAnonymousMethodDelegate1'
   IL_0019: br.s IL_001b
   IL_001b: ldsfld class Lambda/BinOp Lambda::'<>9__CachedAnonymousMethodDelegate1'
   IL_0020: ldc.i4.1
   IL_0021: ldc.i4.2
   IL_0022: call int32 Lambda::Calculate(class Lambda/BinOp,int32,int32)
   IL_0027: stloc.0
   IL_0028: ldloc.0
   IL_0029: call void [mscorlib]System.Console::WriteLine(int32)
   IL_002e: nop
   IL_002f: ret
} // end of method Lambda::Main

 

Quiz

Derive a delegate signature for each of the following lambda expressions and perform an invocation:

  • () => 123
  • () => {}
  • a => 2 * a
  • (a, b) => a * b
  • s => Console.WriteLine("Hello {0}", s);
  • () => { string s = Console.ReadLine(); return s; }

Think about the following code fragment and find out how it works (if it works of course):

using System;

class Lambda
{
   delegate int BinOp(int a, int b);

   static void Main()
   {
      int c = 3;
      int res = Calculate((a,b) => a + b + c, 1, 2);

      Console.WriteLine(res);

   }

   static int Calculate(BinOp op, int a, int b)
   {
      return op(a,b);
   }
}

I'll post about this later on.

kick it on DotNetKicks.com

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

The latest wave of releases at Microsoft has almost come to an end: after Windows Vista and 2007 Office System, Exchange 2007 RTM'd this morning.

On to Orcas, LINQ, ASP.NET Ajax, WPF/E, Longhorn Server (and Vienna?) I guess.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

It's ready! Check it out on Gert's blog:

Have fun!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Introduction

A reader of mine noticed I'm using Visual Studio 2005 as the tool to create all of my Windows Workflow Foundation related samples, instead of taking my favorite minimal command-line approach to create basic samples. So here it is today: a simple Hello World demo of WF using the command-line.

 

Please welcome WFC

Just like csc.exe is the C#'s programmer best friend, wfc.exe plays that role for WF programmers. Basically it turns a .xoml file (which stands for eXtensible Object Markup Language) into a .dll assembly file representing the workflow you've designed. Below you can see a simple demo.xoml file:

<SequentialWorkflowActivity x:Name="Demo" x:Class="FooBar.Demo"
    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
   <CodeActivity x:Name="sayHello" ExecuteCode="sayHello_ExecuteCode">
      <x:Code>
         <![CDATA[
            void sayHello_ExecuteCode(object sender, EventArgs e)
            {
               Console.WriteLine("Hello World");
            }

         ]]>
      </x:Code>
   </CodeActivity>
</SequentialWorkflowActivity>

This simple sample can be compiled into a .dll file by invoking the following:

>wfc demo.xoml

In this case, we've been using a CDATA section to put the code inline between the XOML definition. Another approach would be to put the following in the demo.xoml file:

<SequentialWorkflowActivity x:Name="Demo" x:Class="FooBar.Demo"
    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
   <CodeActivity x:Name="sayHello" ExecuteCode="sayHello_ExecuteCode" />
</SequentialWorkflowActivity>

and to create another file called demo.cs:

using System;

namespace FooBar
{
   partial class Demo
   {
      void sayHello_ExecuteCode(object sender, EventArgs e)
      {
         Console.WriteLine("Hello World");
      }
   }
}

which can be compiled using:

>wfc demo.xoml demo.cs

Notice the use of the partial keyword in the class definition. In the end, the .xoml file is a partial definition of the workflow class, so the .cs file is another part of it and has to be marked as "partial". Both compilations will yield the same assembly:

Using the assembly in a host application is another concern of course. Basically you just have to compile the following piece of code with a reference to the demo.dll file generated above:

using System;
using System.Threading;
using System.Workflow.Runtime;

namespace FooBar
{
   class Hello
   {
      public static void Main()
      {
         using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
         {
            AutoResetEvent waitHandle = new AutoResetEvent(false);

            workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
            {
               waitHandle.Set();
            };

            WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(FooBar.Demo));
            instance.Start();

            waitHandle.WaitOne();
         }
      }
   }
}

which might be a little difficult to add the reference to the System.Workflow assemblies which reside in the GAC. A more convenient demo approach is to merge the host application and the code-behind for the workflow into one single .cs file, like this:

using System;
using System.Threading;
using System.Workflow.Runtime;

namespace FooBar
{
   class Hello
   {
      public static void Main()
      {
         using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
         {
            AutoResetEvent waitHandle = new AutoResetEvent(false);

            workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
            {
               waitHandle.Set();
            };

            WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(FooBar.Demo));
            instance.Start();

            waitHandle.WaitOne();
         }
      }
   }

   partial class Demo
   {
      void sayHello_ExecuteCode(object sender, EventArgs e)
      {
         Console.WriteLine("Hello World");
      }
   }

}

Now compile this file (demo.cs) together with the .xoml file, as follows:

>wfc /target:exe /r:System.Xml.dll demo.xoml demo.cs

 

MsBuild style

There's of course another approach that leans more towards Visual Studio 2005 compilation, i.e. using MsBuild. Assuming you have a file called demo.xoml:

<SequentialWorkflowActivity x:Name="Demo" x:Class="FooBar.Demo"
    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
   <CodeActivity x:Name="sayHello" ExecuteCode="sayHello_ExecuteCode">
      <x:Code>
         <![CDATA[
            void sayHello_ExecuteCode(object sender, EventArgs e)
            {
               Console.WriteLine("Hello World");
            }

         ]]>
      </x:Code>
   </CodeActivity>
</SequentialWorkflowActivity>

and a file called hello.cs:

using System;
using System.Threading;
using System.Workflow.Runtime;

namespace FooBar
{
   class Hello
   {
      public static void Main()
      {
         using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
         {
            AutoResetEvent waitHandle = new AutoResetEvent(false);

            workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
            {
               waitHandle.Set();
            };

            WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(FooBar.Demo));
            instance.Start();

            waitHandle.WaitOne();
         }
      }
   }
}

you can create a .csproj build file that contains this:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <RootNamespace>FooBar</RootNamespace>
    <AssemblyName>Demo</AssemblyName>
    <OutputPath>.</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Workflow.Activities" />
    <Reference Include="System.Workflow.ComponentModel" />
    <Reference Include="System.Workflow.Runtime" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Hello.cs">
      <DependentUpon>demo.xoml</DependentUpon>
      <SubType>Component</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <Content Include="demo.xoml"/>
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets" />
</Project>

which can be built using:

>msbuild

Enjoy command-line compiling WF-apps (for demo purposes only I hope)!

kick it on DotNetKicks.com

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

 

Introduction

In this C# 3.0 Feature Focus Week we'll focus on the new language features that will be part of C# 3.0 "Orcas". As you already might know, the major innovation on Orcas is the LINQ (Language Integrated Query) technology that will make data queries a first class citizen of the language (C# 3.0 and VB 9.0). In order to unlock this potential, a set of language features were added to the language that all work in concert to enable LINQ stuff. However, all of those individual features prove to be useful in isolation as well. Later, we'll focus on LINQ itself.

 

Extension Methods

To set our minds, assume the following scenario: you're doing a lot of string manipulations and one of the operations you need quite often is reversing a string. Since strings are immutable, a new string has to be created with the reversed set of characters in it. A typical solution looks like this:

using System;

class ReverseStringDemo
{
   public static void Main()
   {
      string s = "Hello World!";
      string r = Helpers.Reverse(s);
   }
}

static class Helpers
{
   public static string Reverse(string s)
   {
      char[] c = s.ToCharArray();
      Array.Reverse(c);
      return new string(c);
   }
}

Although this approach works like a charm, it has a few drawbacks. First of all, the code is less intuitive because of the need to call a static method which happens to be defined in "some" static class. (Note: Static classes were introduced in C# 2.0 as a way to enforce - at compile time - all member of a class to be static. This feature was the direct result of an API issue in .NET Framework 1.1 where an instance member was added to the System.Environment class which didn't have a public constructor, so the newly added instance member was useless. As the matter in fact, the member had to be static but the error was not caught at compile time. Static classes avoid this kind of problem to arise.) Another drawback is the disruptive nature when results have to be chained. Assume the following:

      string s = "Hello World!";
      string t = s.TrimLeft().ToLower();
      string r = Helpers.Reverse(t).Substring(0, 15).PadRight(20, '*');

It would be much nicer to be able to write everything in one chain of calls, like this:

      string s = "Hello World!";
      string r = s.TrimLeft().ToLower().Reverse().Substring(0, 15).PadRight(20, '*');

This becomes even more convenient when a lot of "extensions" would have to be added, for example to every possible collection type which is exactly what LINQ needs to do: take a collection, filter items based on a predicate, sort it, group the results, project, etc. Basically, this is a chain of calls that transforms one collection into another, like this:

      var result = customers.Where(c => c.Age >= 18).Select(new { c.Name, c.Age });

Extension methods allow us to realize this. Basically, you can turn static methods on a static class into extension methods by just adding the this keyword to the first method parameter:

using System;

class ReverseStringDemo
{
   public static void Main()
   {
      string s = "Hello World!";
      string r = s.Reverse();
   }
}

static class Helpers
{
   public static string Reverse(this string s)
   {
      char[] c = s.ToCharArray();
      Array.Reverse(c);
      return new string(c);
   }
}

Note: The extension method can still be used as a regular static method too, so you can turn existing static methods (on static classes) into extension methods without breaking compatibility.

The Main method in the code fragment above is turned into the following IL code:

.method public hidebysig static void Main() cil managed
{
   .entrypoint
   .locals init (string V_0,
            string V_1)
   IL_0000: nop
   IL_0001: ldstr "Hello World!"
   IL_0006: stloc.0
   IL_0007: ldloc.0
   IL_0008: call string Helpers::Reverse(string)
   IL_000d: stloc.1
   IL_000e: ret
} // end of method ReverseStringDemo::Main

As you can see, extension methods are just some syntactical sugar to masquerade static methods calls, in order to make source code cleaner and more intuitive.

The Reverse method is translated in a regular static method but annotated with an attribute that makes it recognizable by the compiler as an extension method:

.method public hidebysig static string Reverse(string s) cil managed
{
   .custom instance void System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
   .locals init (char[] V_0,
            string V_1)
   IL_0000: nop
   IL_0001: ldarg.0
   IL_0002: callvirt instance char[] [mscorlib]System.String::ToCharArray()
   IL_0007: stloc.0
   IL_0008: ldloc.0
   IL_0009: call void [mscorlib]System.Array::Reverse(class [mscorlib]System.Array)
   IL_000e: nop
   IL_000f: ldloc.0
   IL_0010: newobj instance void [mscorlib]System.String::.ctor(char[])
   IL_0015: stloc.1
   IL_0016: br.s IL_0018
   IL_0018: ldloc.1
   IL_0019: ret
} // end of method Helpers::Reverse

In case the library with extension methods is compiled into another namespace  (maybe in another .dll file), you need to bring these into scope using the using statement. An example will make this clear:

using System;
using System.Collections.Generic;

namespace Bar
{
   using Foo;

   class Ext
   {
      public static void Main()
      {
         string s = "Hello world!";
         string r = s.Reverse();
         Console.WriteLine(r);

         List<string> lst = new List<string> { "Bart", "Steve", "Rob", "John", "Bill" };
         foreach (string t in lst.Where(i => i.Length == 4))
            Console.WriteLine(t);
      }
   }
}

namespace Foo
{
   delegate R Func<T,R>(T t);

   static class Extensions
   {
      public static string Reverse(this string s)
      {
         char[] c = s.ToCharArray();
         Array.Reverse(c);
         return new string(c);
      }

      public static IEnumerable<T> Where<T>(this IEnumerable<T> sequence, Func<T, bool> predicate)
      {
         foreach (T item in sequence)
            if (predicate(item))
               yield return item;
      }
   }
}

In the code fragment above you can see the use of using Foo to bring extensions defined in the Foo namespace in scope. This makes the Reverse and Where methods available on System.String and System.Collections.Generic.IEnumerable<T> respectively. The latter method is a sample of an extension method applied to an interface, which is as easy as an extension method on a regular type. To understand the Where method sample, you should know about iterators (a C# 2.0 feature). You can read more on iterators on my C# 2.0 Iterators blog post. The Where method sample is equivalent to the Where operator in LINQ and can be found in my LINQ-SQO CodePlex project as well. Essentially, it takes a predicate (which is a method that maps an "item" on a boolean value) to filter items from the source "sequence" (a synonym for an IEnumerable<T> collection type). In the samp,e all strings with a length of 4 characters are retained.

Tke key takeaway from this post is that extension methods are a convenient way to extend types with instance methods without requiring access to the orginal source code. As usual, use it with care. LINQ uses extension methods extensively, as we'll explain later on. Have fun!

kick it on DotNetKicks.com

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Sorry for the lack of posts the last three days but there are currently some technical difficulties with my website that have caused the posts of the first week of December to disappear :s. I'm investigating the problem and will put the posts onine again as soon as possible, starting with the C# 3.0 Feature Focus Week.

PS: In the meantime I've found some time to reinstall my machine with the RTM versions of Windows Vista and Office 2007, which run like a train. I'll blog about setup experiences soon as I had some minor difficulties on my machine (for God - or Murphy - knows what reason). As the matter in fact, I couldn't delay the installation anymore since I had to deliver sessions on both technologies last week on the AAL (Anytime Anywhere Learning) summit in Brussels last Monday for Flemish education people. And despite some voice troubles the audience pretty much liked the new technology which makes me a happy man once more :-).

Update 12/06/2006 7:39 PM GTM+1 - Problem solved: Apparently there was some mismatch between the online server configuration and the offline blogger app concerning the date/time format. The problem caused the posts for December 3rd, 4th and 5th to appear on March 12th, April 12th and May 12th respectively. Everything seems to be fine now. Apologies for the inconvenience :-).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

 

Introduction

In this C# 3.0 Feature Focus Week we'll focus on the new language features that will be part of C# 3.0 "Orcas". As you already might know, the major innovation on Orcas is the LINQ (Language Integrated Query) technology that will make data queries a first class citizen of the language (C# 3.0 and VB 9.0). In order to unlock this potential, a set of language features were added to the language that all work in concert to enable LINQ stuff. However, all of those individual features prove to be useful in isolation as well. Later, we'll focus on LINQ itself.

 

Collection Initializers

Everyone reading my blog should be familiar with this kind of code:

using System;

class Cini
{
   public static void Main()
   {
      string[] s1 = new string[] { "Bart", "John", "Rob" };
      string[] s2 = { "Bart", "John", "Rob" };
   }
}

Quite convenient to initialize an array right away. However, did you ever try this?

using System;
using System.Collections.Generic;

class Cini
{
   public static void Main()
   {
      List<string> l = new List<string>() { "Bart", "John", "Rob" };
   }
}

In C# 2.0, this doesn't work. You can already guess what the outcome will be in C# 3.0, it works indeed! (Note: the short syntax without a new initialization instruction doesn't work however - CS0622). In reality, the code above is translated into:

using System;
using System.Collections.Generic;

class Cini
{
   public static void Main()
   {
      List<string> l = new List<string>();
      l.Add("Bart");
      l.Add("John");
      l.Add("Rob");
   }
}

Verification in the IL code proves this:

.method public hidebysig static void Main() cil managed
{
   .entrypoint
   .locals init (class [mscorlib]System.Collections.Generic.List`1<string> V_0,
            class [mscorlib]System.Collections.Generic.List`1<string> V_1)
   IL_0000: nop
   IL_0001: nop
   IL_0002: newobj instance void class [mscorlib]System.Collections.Generic.List`1<string>::.ctor()
   IL_0007: stloc.1
   IL_0008: ldloc.1
   IL_0009: ldstr "Bart"
   IL_000e: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
   IL_0013: nop
   IL_0014: ldloc.1
   IL_0015: ldstr "John"
   IL_001a: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
   IL_001f: nop
   IL_0020: ldloc.1
   IL_0021: ldstr "Rob"
   IL_0026: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
   IL_002b: nop
   IL_002c: ldloc.1
   IL_002d: nop
   IL_002e: stloc.0
   IL_002f: ret
} // end of method Cini::Main

Behind the scenes, the compilers checks to see whether the type used implements IEnumerable and has a suitable Add method overload. So, doing the same with a non-generic collection like ArrayList won't work (CS1801: "The member initializer does not have an identifiable name") - update: this remark doesn't apply to the RTM release anymore:

using System;
using System.Collections;

class Cini
{
   public static void Main()
   {
      ArrayList l = new ArrayList() { "Bart", "John", "Rob" };
   }
}

An example to see this work against a self-made collection is shown below. For our convenience, we just wrap the List<T> collection type inside our own collection:

using System;
using System.Collections.Generic;

class Cini
{
   public static void Main()
   {
      Bar<string> b = new Bar<string> { "Bart", "John", "Rob" };
   }
}

public class Bar<T> : ICollection<T>
{
   private List<T> lst = new List<T>();

   public virtual void Add(T item)
   {
      Console.WriteLine(item);
      lst.Add(item);
   }

   public virtual void Clear()
   {
      lst.Clear();
   }

   public virtual void CopyTo(T[] item, int n)
   {
      lst.CopyTo(item, n);
   }

   public virtual bool Contains(T item)
   {
      return lst.Contains(item);
   }

   public virtual int Count
   {
      get { return lst.Count; }
   }

   public virtual bool IsReadOnly
   {
      get { return ((ICollection<T>)lst).IsReadOnly; }
   }

   public virtual bool Remove(T item)
   {
      return lst.Remove(item);
   }

   public virtual IEnumerator<T> GetEnumerator()
   {
      return lst.GetEnumerator();
   }

   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
   {
      return ((System.Collections.IEnumerable)lst).GetEnumerator();
   }
}

Compiling and executing this code will print Bart, John and Rob on separate lines on the screen.

This feature becomes even more useful when combined with object initializers which were the subject of part 2 of this C# 3.0 Feature Focus series:

using System;
using System.Collections.Generic;

class Cini
{
   public static void Main()
   {
      List<Customer> customers = new List<Customer>() {
         new Customer { Name = "Bart", City = "Ghent"  Age = 23 },
         new Customer { Name = "John", City = "Zottegem", Age = 58 },
         new Customer { Name = "Rob" , City = "Schoten",  Age = 21 }
      }
;
   }
}

Try the same in C# 2.0 to see the difference with your own eyes. A quick calculation learns that we'd need 16 lines of code to achieve the same. Enjoy!

kick it on DotNetKicks.com

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts « Previous page - Next page »