Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#

Functional Programming in C# 3.0 using Lambda Expression - Part 1

Rate me:
Please Sign up or sign in to vote.
3.71/5 (8 votes)
12 Feb 2009CC (ASA 2.5)4 min read 56.7K   37   7
This article explains how to use C# 3.0 lambda expression for functional programming.

Introduction

C# was born in an object oriented programming family and started evolving to adopt the characteristics from other programming languages as well the functional programming family. It laid its foundation to adopt functional programming since version 1.0 with delegates and some partial adoptions found in C# 2.0. Finally, it smartly adopts functional programming style with OO.

In this article, I will explain how to write programs in a functional manner using C# 3.0. If you are new to functional programming or do not know the benefits of it, read my two part articles, Introduction to Functional Programming using F# Part 1 and Part 2. These articles are mainly focused on explaining the fundamentals and benefits of functional programming and the famous lambda calculus theory.

Factors for Functional Programming Adoption

As I explained in my article, Introduction to Functional Programming using F#, there are eight factors that need to be supported by a programming language for functional programming. There are:

  1. Anonymous function name
  2. Type inference
  3. Parameterized types
  4. High order functions
  5. Immutable data structure
  6. Recursion
  7. Currying
  8. Lazy evaluation

I am going to explain how C# 3.0 adopts or satisfies these factors with necessary details.

Delegates

Delegates are managed callback methods which are introduced in C# 1.0 and much improved in C# 2.0. This enables to wire up a caller to the target method dynamically. There are two aspects in delegates:

  • Delegate type. This declares delegate with the signature of the target method.
  • Delegate instance. Wiring up a method.

Code 1 shows a sample program which declares a delegate and assigns a caller to invoke a target method.

C#
// Code 1
// Delegate
delegate int MathFunc(int x); // delegate type

static void Main(string[] args)
{
    MathFunc mf = Square; // Square is an instance of the delegate MathFunc
    int result = mf(3);
    Console.WriteLine(result); // output: 9
    Console.ReadLine();
}

static int Square(int x) {return x * x;}

Actually, the code MathFunc mf = Square means MathFunc mf = new MathFunc(Square). The later is C# 1.0 syntax. Delegate is fundamental for the concepts in C# 3.0 that satisfy the functional programming factors.

Anonymous Methods

In Code 1, you need to give the method name Square to the instance mf. This makes the code a bit clumsy. C# 2.0 introduces anonymous methods in which you can assign a method (actually a method body) without any name using the delegate keyword. See Code 2.

C#
// Code 2
// Anonymous method
delegate int MathFunc(int x);

static void Main(string[] args)
{
    MathFunc mf = delegate(int x) { return x * x; }; // anonymous method
    int result = mf(3);
    Console.WriteLine(result);
    Console.ReadLine();
}

This syntax reduces the coding overhead in instantiating delegates by eliminating the need to create a separate method. This feature satisfies the functional factor #1 anonymous function name.

Generics

Generics is the most notable and powerful feature introduced in C# 2.0. This allows to define type-safe data structure, without specifying the target type for the data structure. This opens another way of reusability using the "template" model. This improves type safety so that there is no need to do sluggish type casting. Code 3 shows a very simple example using generics.

C#
// Code 3
// Very light example for Generics
IEnumerable<int /> myints =
           new List<int /> { 1, 1, 2, 3, 5, 8, 11 };

foreach (int i in myints)
	Console.Write("{0}\t", i);

Lambda Expression

One of the most notable features introduced in C# 3.0 is lambda expression. This is C# 3.0's version of anonymous methods written in place of a delegate instance. To know more about lambda expression, visit this link. Code 4 demonstrates the usage of lambda expression.

C#
// Code 4
// Lambda Expression
delegate int MathFunc(int x); // usual delegate type declaration

static void Main(string[] args)
{
    MathFunc mf = x => return x * x; // lambda expression in place of
				// delegate instance
    int result = mf(3);
    Console.WriteLine(result);
    Console.ReadLine();
}

The lambda expression makes the code much lighter. The interesting point is that you do not need to give type information for the arguments (or bound variables - hope you remember) in Code 4, x. There is no magic behind lambda expressions and the compiler itself. The compiler knows and infers the type from the delegate type. This is called type inference which satisfies the functional factor #2.

Generic Lambda Expression

Using lambda expression, Code 4 looks simple. However, whenever a lambda expression is required, we need to define a delegate type for this. This is very awkward and less productive. .NET 3.5 introduces generic delegate which simplifies the lambda expression much better and simpler. It provides two pre-defined generic delegates Func and Action. Using these delegates, you do not need to explicitly define a delegate. The difference between Func and Action is the return type. Func supports return type however Action supports methods with void return type. These delegates provide a set of pre-defined signatures that are ready to use.

C#
// Pre-defined Func delegates
delegate TResult Func<T>();
delegate TResult Func<T1,TResult>(T1 arg1);
delegate TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2);
delegate TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3);
delegate TResult Func<T1,T2,T3,T4,TResult>T1 arg1, T2 arg2, T3 arg3, T4 arg4);

// Pre-defined Action delegates
delegate void Action<T>(T1 arg1);
delegate void Action<T1,T2>(T1 arg1, T2 arg2);
delegate void Action<T1,T2,T3>T1 arg1, T2 arg2, T3 arg3);
delegate void Action<T1,T2,T3,T4>T1 arg1, T2 arg2, T3 arg3, T4 arg4);

Let us see how this and other C# 3.0 features satisfy the remaining functional factors in Part 2 of this article.

References

You can download and see my two part screen cast about Functional Programming using C# 3.0 from my skydrive here.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


Written By
Architect Aditi
India India
Working as Architect for Aditi, Chennai, India.

My Website: www.udooz.net

My Blog: www.udooz.net/blog

Comments and Discussions

 
QuestionThanks! BTW.. Part 2 link is broke... Pin
coxad26-Feb-15 10:59
coxad26-Feb-15 10:59 
QuestionWhat is the "/" in <int /> Pin
HenryBStinson7-Sep-12 9:03
HenryBStinson7-Sep-12 9:03 
GeneralMy vote of 4 Pin
Nandu0914-Mar-11 5:21
Nandu0914-Mar-11 5:21 
GeneralSyntax problem Pin
Dejan Petrovic21-Feb-09 21:58
Dejan Petrovic21-Feb-09 21:58 
GeneralRe: Syntax problem Pin
Tamas Koszoru14-Sep-11 1:42
Tamas Koszoru14-Sep-11 1:42 
GeneralImproving Pin
Gabe Anguiano5-Feb-09 17:39
Gabe Anguiano5-Feb-09 17:39 
GeneralRe: Improving Pin
M Sheik Uduman Ali11-Feb-09 15:29
M Sheik Uduman Ali11-Feb-09 15:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.