LINQ is a new feature added to C# 3.0. For an introduction to LINQ, please visit here
So, how are we able to use LINQ seamlessly with C#? Thanks to some of the enhancements that were made to C# for LINQ. They are as follows,
1) Lambda Expressions
2) The var Keyword
3) Extension Methods
4) Partial Methods
5) Expression Trees
This is the start of 3 part series which would be,
· Part 1 – Lambda Expressions
· Part 2 – The var Keyword, Extension Methods and Partial Methods
As said above, this post will be explaining about Lambda Expressions
Lambda Expressions
Lambda Expression is an anonymous function that can contain an expression or statement or can also be used to create a delegate.
To understand Lambda Expressions, it is better to first look into,
1) Named Methods
2) Anonymous Methods
Named Methods
With delegates one can create Named Methods, that is, instantiate a named method to a delegate and invoke it
Nothing gets explained better without an example; so, let’s get into our sample application
Sample Application
We are going to create a sample application which is going to filter names that contains a character. It’s a very basic and simple example, but it’s really good to explain the things that we want to explore. We would be seeing on how we approach the same concept using Named Methods and Anonymous Methods and then come to Lambda Expressions.
We have a small class called Utility which looks like this,
It has got two static methods and a delegate called CustomFilter with an input parameter as string and bool as return type. So, the idea is to allow the developer or user to write their own custom filter function, but use this Utility to filter. This is done with the help of delegates.
Using Named Methods
So, if we take our Named Method approach, we would end up doing like this,
static void UsingNamedMethods()
{
List<string> FilteredNames =
Utility.FilterNames(names, MyFilter);
foreach (string name in FilteredNames)
Console.WriteLine(name);
}
static bool MyFilter(string name)
{
if (name.Contains(‘c’))
return true;
return false;
}
We have a method called MyFilter which is where we define our custom filter logic and instantiate the delegate CustomFilter with this method using the Utility.FilterNames function
And here is our Utility.FilterNames function
public delegate bool CustomFilter(string name);
public static List<string>
FilterNames(string[] names,CustomFilter customFilter)
{
List<string> NamesList = new List<string>();
foreach(string name in names)
{
if (customFilter(name))
NamesList.Add(name);
}
return NamesList;
}
It’s fairly simple and straight forward. Now we really have something useful which makes use of Named Methods. This sample will help the Customer who is going to use our Utility to write his own Filter and use the generic FilterNames function to filter it.
Look into our filter method which is Myfilter – It’s fairly simple, just checking whether the name contains a character and returns true if so. Do we really need to write a method for this? Why can’t we specify a code block instead and make use of it? Anonymous Methods comes to our rescue!
Anonymous Methods
Anonymous methods can be used to pass a code block to a delegate, using the delegate parameter, and can be used in places where creating a method is really not necessary, like in our example.
Using the Anonymous method, our code changes to,
static void UsingAnonymousMethods()
{
List<string> FilteredNames;
FilteredNames =
Utility.FilterNames(names,
delegate(string name)
{
return (name.Contains(‘c’));
} );
foreach (string name in FilteredNames)
Console.WriteLine(name);
}
So, now we have a code block which checks for a character in the name and it is passed as our CustomFilter delegate
Note that our FilterNames Utility function remains unchanged.
However, Anonymous methods do have one drawback in regard to readability. It’s more verbose and the code block sometimes becomes really hard to read!
So, do we really have anything which is easy to read and also simple to use? – Yes, and Lambda Expressions comes to our rescue!
Revisiting Lambda Expressions
As I said earlier – Lambda Expression is an anonymous function that can contain an expression or statement or can also be used to create a delegate
The structure of a lambda expression looks like this,
(param1,param2..paramN)=>expression
Basically we have some input parameters delimited with comma on the left and a corresponding expression on the right
The simplest lambda expression is,
x=>x
This is nothing but assigning x to x
Moving forward, our sample’s expression to find a character in the name would now become,
n=>n.Contains(‘c’)
How is the type of ‘n’ inferred? Remember our delegate? Here it is again,
public delegate bool CustomFilter(string name);
If you translate in pure English – Here is a delegate called CustomFilter which accepts one input parameter of type string and returns a value of type bool
So, when we actually make use of lambda expressions, this gets inferred and thus our ‘n’ in the above lambda expression gets inferred that it is of type string and has to return bool. But when inferring types is not possible, you could always do,
(string n)=>n.Contains(‘c’)
This would explicitly specify the type of ‘n’
Coming back to our sample application, now with the use of lambda expressions, we could write,
static void UsingLambdaExpressions()
{
List<string> FilteredNames;
FilteredNames = Utility.FilterNames(names, n => n.Contains(‘c’));
foreach (string name in FilteredNames)
Console.WriteLine(name);
}
Note that our FilterNames Utility function still remains unchanged.
Statement Lambdas
Again, revisiting our lambda expression definition – Lambda Expression is an anonymous function that can contain an expression or statement or can also be used to create a delegate
We did see that lambda expression that has an expression. What about a statement?
Statement lambdas look like,
(param1,param2..paramN)=>{ statement; }
The statement body can contain many statements instead of a single expression. Something like,
FilteredNames =
Utility.FilterNames(
names,
n =>{
bool blnVal;
/*… something here …*/
blnVal = n.Contains(‘c’);
return blnVal;
} );
Lambdas with Func<T,TResult> delegates
Again, revisiting our lambda expression definition – Lambda Expression is an anonymous function that can contain an expression or statement or can also be used to create a delegate
We did see that lambda expression that has an expression, a statement. What about the last one which can be used to create a delegate?
With the Func<T,TResult> family of generic delegates, we can use lambda expressions to create a delegate and invoke it.
Before getting into an example, let us explore the Func<T,TResult> family. We currently have,
A Simple example would be,
Func<string, bool> SampleFunction = n =>n.Contains(‘c’);
SampleFunction(“Chirstchurch”);
The above code block looks fairly simple and actually we see that we can eliminate Named Methods and Anonymous Methods now and directly make use of lambda expressions!
Coming back to our example, we can now simplify our FilterNames Utility function to something like this,
public static List<string> FilterNamesUsingFuncDelegates
(string[] names,Func<string,bool> customFilter)
{
List<string> NamesList = new List<string>();
foreach (string name in names)
{
if (customFilter(name))
NamesList.Add(name);
}
return NamesList;
}
Yes, you are right; we no need to declare any delegate now and make use of the available function delegates as Predicates!
Predicates were introduced in .NET 2.0 and are defined as (from MSDN),
Represents the method that defines a set of criteria and determines whether the specified object meets those criteria
You can read more about Predicates here
We can come across the same in LINQ when you use Standard Query Operators. If you remember our LINQ example, we have actually seen this,
IEnumerable<string> query = names
.Where(n => n.Equals(matchName))
.Select();
And Where clause syntax is,
You can download the sample application here
Useful Resources
Nice, but i’m looking for something more complex when using the contains.
class foo {
int num;
int name;
}
List stuff = new List();
…
add some stuff…
…
later on…
…
public bool hasName(string _name) {
return stuff.Contains(x=> x.name == _name);
}
or something like that. I want to see if one of the objects in the list has a particular value. but I keep getting errors when I try to do that. Maybe it’s my includes?
Thanks,
duh, use exists, not contains…. stupid mixed up names. Course if you use a dictionary you’ll be hosed. dic.Values doesn’t have an Exists
@mike, Here is a solution for HasName
public static bool HasName(string _name)
{
var q = stuff.Where(s => s.Contains(_name)).FirstOrDefault();
if (q != null)
return true;
else
return false;
}
You use Where to find and not Contains 🙂
If this was plain sql type LINQ query, it would be :
var q = (from s in stuff
where s == _name
select s).FirstOrDefault();