Posts Tagged ‘C#’

A C# Interface for Dependency Injection

May 27, 2010

This is a follow-up to Jesse Liberty’s Answering A C# Question blog post which compares two equivalent code examples to illustrate the value of interfaces:

  1. No interface example
  2. Interface with Dependency Injection (DI) example

Both examples use fictitious Notepad functionality with File and Twitter capability.

Example #1 does not use an interface and the line of code (LOC) count is 49.

Example #2 uses a Writer interface with Parameter Dependency Injection. The Notepad’s dependent objects (e.g., FileManager and TwitterManager) are passed as parameters (aka injected) to the worker method. In this case, the LOC count is 57.

It’s interesting to note that the interface example has slightly more code. The big win is less coupling which is much easier to maintain and more testable. I’ll have more about the testability in a future post.


Example 1 – No Interface

using System.IO;
using System;

namespace Interfaces
{
   class Program
   {
      static void Main( string[] args )
      {
         var np = new NotePad();
         np.NotePadMainMethod();
      }
   }

   class NotePad
   {
      private string text = "Hello world";

      public void NotePadMainMethod()
      {
         Console.WriteLine("Notepad interacts with user.");
         Console.WriteLine("Provides text writing surface.");
         Console.WriteLine("User pushes a print button.");
         Console.WriteLine("Notepad responds by asking ");
         Console.WriteLine("FileManager to print file...");
         Console.WriteLine("");

         var fm = new FileManager();
         fm.Print(text);

         var tm = new TwitterManager();
         tm.Tweet(text);
      }
   }

   class FileManager
   {
      public void Print(string text)
      {
         Console.WriteLine("Pretends to backup old version file." );
         Console.WriteLine("Then prints text sent to me." );
         Console.WriteLine("printing {0}" , text );

         var writer = new StreamWriter( @"HelloWorld.txt", true );

         writer.WriteLine( text );
         writer.Close();
      }
   }

   class TwitterManager
   {
      public void Tweet( string text )
      {
         // write to twitter
         Console.WriteLine("TwitterManager: " + text);
      }
   }
}

Example 2 – Writer Interface with Parameter Dependency Injection

using System.IO;
using System;

namespace Interfaces
{
   class Program
   {
      static void Main( string[] args )
      {
         var np = new NotePad();

         var fm = new FileManager();
         var tm = new TwitterManager();

         np.NotePadMainMethod(fm); // parameter injection
         np.NotePadMainMethod(tm); // parameter injection
      }
   }

   class NotePad
   {
      private string text = "Hello world";

      public void NotePadMainMethod(Writer w)
      {
         Console.WriteLine("Notepad interacts with user.");
         Console.WriteLine("Provides text writing surface.");
         Console.WriteLine("User pushes a print button.");
         Console.WriteLine("Notepad responds by asking ");
         Console.WriteLine("FileManager to print file...");
         Console.WriteLine("");

         w.Write(text);
      }
   }

   // Writer Interface
   interface Writer
   {
      void Write(string whatToWrite);
   }

   class FileManager : Writer  // Inherits Writer Interface
   {
      // Implements Write Interface Method
      public void Write(string text)
      {
         // write to a file
         Console.WriteLine("FileManager: " + text);
      }

      public void Print(string text)
      {
         Console.WriteLine("Pretends to backup old version file." );
         Console.WriteLine("Then prints text sent to me." );
         Console.WriteLine("printing {0}" , text );

         var writer = new StreamWriter(@"HelloWorld.txt", true);

         writer.WriteLine(text);
         writer.Close();
      }
   }

   class TwitterManager : Writer  // Inherits Writer Interface
   {
      // Implements Write Interface Method
      public void Write( string text )
      {
         // write to Twitter stream
         Console.WriteLine("TwitterManager: " + text);
      }
   }
}

Advertisements

Lambda Expressions

January 3, 2006

The origins of the term Lambda Expression can be traced to an American mathematician Alonzo Church. He published a paper in 1936 that introduced Lambda Calculus.

Lambda Calculus is used to investigate:

  • function definition
  • function application (implementation)
  • recursion

Lambda Calculus was influential in the design of LISP and eventually all functional programming languages.

You can find more info on LISP here.

The key capability of a lambda expression is that it provides a concise natural way to pass a code block as a parameter.

In C#, a lambda expression is implemented as an anonymous method.

Before we go further it is important to know about delegates.

A delegate is a data structure that refers to one or more methods, and for instance methods, it also refers to the corresponding object instance. The closest equivalent of a delegate in C/C++ is a function pointer. However, a C/C++ function pointer can only reference static functions. A delegate can reference both static and instance methods.


Simple C# Delegate Example: (20 lines of code)

using System;

class DelegateTest
{
  delegate void DelegateType();  // delegate method declaration

  static DelegateType GetMethod()
  {
    return new DelegateType(MethodBody);
  }

  static void MethodBody()       // method definition
  {
    Console.WriteLine("Hello");
  }

  static void Main()
  {
    DelegateType delegateInstance = GetMethod();

    delegateInstance();  // invokes method
    delegateInstance();  // invokes method again

    Console.ReadKey();
  }
}

C# 2.0 introduces anonymous methods, which allow code blocks to be written ‘inline’ where delegate values are expected.

using System;
 
class Program 
{ 
  delegate void DelegateType();  // delegate method declaration
 
  static DelegateType GetMethod() 
  { 
    return delegate() { Console.WriteLine("Hello");};
                                 // anonymous method
  }
 
  static void Main() 
  { 
    DelegateType delegateInstance = GetMethod();
 
    delegateInstance();  // invokes method
    delegateInstance();  // invokes method again
 
    Console.ReadKey(); 
  } 
}

Example of Anonymous Method with two parameters.

using System; 

class Program
{
  // delegate method declaration
  delegate void DelegateType(string name, int val);

  static DelegateType GetMethod()
  {
    // anonymous method with parameters
    return delegate(string name, int val)
      { Console.WriteLine(
           "Hello name:{0} - value:{1}", name, val
                         );};
  }

  static void Main()
  {
    DelegateType delegateInstance = GetMethod();

    delegateInstance("Henry David Thoreau", 44);
                            // invokes method

    delegateInstance("Sandra Day O’Connor", 23);
                            // invokes method again

    Console.ReadKey();
  }
}

The Anonymous Method feature is unique to C#. Don Box refers to it as closure.

Java’s equivalent is inner classes and anonymous inner classes.

Java Anonymous Inner Class Example

public class MyClass extends Applet 
{ 
  ... 
  someObject.addMouseListener(new MouseAdapter()  
  {  // anonymous class definition and
     // instantiation here
     public void mouseClicked(MouseEvent e)  
     {  
       ...//Event listener code here...
     }  
  }  ); 
  ... 
}

C# Lambda Expression

C# 3.0 introduces lambda expressions, to provide a more concise way to write anonymous methods.

To illustrate, let’s see an anonymous method sample and then compare it to a lambda expression version.

Another C# Anonymous Method Example

class Lambda
{
  static void TestLambdaExpression()
  {
    List list = new List();
    list.Add(1);
    list.Add(2);
    list.Add(3);
    list.Add(4);
 
    // FindAll() calls an anonymous method
    List evenNumbers =
      list.FindAll(delegate(int i) { return (i % 2) == 0; } );
 
    foreach (int evenNumber in evenNumbers)
    {
      Console.WriteLine(evenNumber);
    }
  }
 
  static void Main(string[] args)
  {
    TestLambdaExpression();
  }
}

C# Lambda Expression Example

class Lambda 
{ 
  static void TestLambdaExpression() 
  { 
    var list = new List();
 
    list.Add(1); 
    list.Add(2); 
    list.Add(3); 
    list.Add(4);
 
    // FindAll() contains a Lambda Expression =>
    var evenNumbers = list.FindAll(i => (i % 2) == 0);
 
    foreach (int evenNumber in evenNumbers) 
    { 
      Console.WriteLine(evenNumber); 
    } 
  }
 
  static void Main(string[] args) 
  { 
    TestLambdaExpression(); 
  } 
}

So we see that a lambda expression is written as a parameter list, followed by the => token, followed by an expression.

Examples:

  (int x) => x + 1         // parameter list, expression
  (int i) => (i % 2) == 0  // parameter list, expression

Please note that the parameter list can be explicitly typed or implicitly typed.

For an implicitly typed parameter list, the parameter type is inferred from the context in which the lambda expression is used. Also, if a lambda expression has a single, implicitly typed parameter, then the parentheses can be omitted. So this works too.

   x => x + 1         // parameter list, expression
   i => (i % 2) == 0  // parameter list, expression

Here is a case with multiple parameters:

   (x,y) => return x * y;  // parameter list, expression

Well that’s enough intro to Lambda Expressions.

I will follow up with a part 2 to show Expression Trees and how LINQ uses it to pass code as parameters.

If interested in LISP, you can find examples of LISP Lambda Expressions here.