I thought of naming this post “Evolution of lambdas in C#”, then I decided that wouldn’t be closest appropriate name for the example that I wanted to discuss. The key to understand a lambda in C# is to understand a delegate. Besides the overly blatant blather – “delegates are nothing but function pointers”, I am going to assert that delegates in C# are very similar to function pointers in C or C++ ;). What did I say? OK!

Let’s get one thing straight, think about the paradigm of passing arguments to a method. A method with a parameter named int  i, would allow you to pass any argument like 1, 2, 3, 4, 5, 6, 7, 8, …32767…2147483647.

method(int i)
{
return;
}

So we sort of seem to get a flexibility there (basis of why we wanted a method in programming – reuse, and possibly call it with different arguments), instead of a method that takes a fixed argument, we have a flexibility to pass in a whole range of values. int is a data type. i is the parameter name, those numbers above are arguments. Very easy concept that any programmer under the sun wouldn’t even dare to defy. In case he did, we would all think he’s crazy, or he lost his brains somewhere towards obsession of trying to defy otherwise. Hey, easy, no arguments about the arguments there!

So somehow, we started writing methods to do repetitive actions. And then “fathers of computer programming” thought of passing a method itself as a argument to a method (a method with a parameter, that accepted a certain type of function – just like the way the data type int allowed us to pass 1, 2, 3, 4,….). But we had to do something extra to pass a function as an argument (we will have to define what our delegate is). int had a whole range of values defined – those numbers above. so we did not really have to re-define what an a int really was. For all we know is int is a datatype defined by the language that accepts certain values as arguments.

Well, in case of delegates, we are free to choose the arguments (or the possible set of values that a delegate type can accept). For instance, lets define a delegate in pseudo-code

public delegate int DoSomeMath(int a, int b);

so we defined a delegate!

delegate is a type, just as how int a is a type. We already know that int accepts the numbers above and it constrains itself to the boundaries of those numbers i.e, from 0 to 2147483647, considering signed integer, because the language/compiler writers programmed it that way. Now, the delegate DoSomeMath is capable of accepting any method that takes two int as input and returns an int as output; it constrains itself to any method that takes two int as input and returns an int as output.

What this means is, we can have methods like below, and they all qualify to be the accepted by the delegate type named DoSomeMath .

public int Add(int i, int j) { return i + j; }

public int Sub(int i, int j) { return i - j; }

public int Mul(int i, int j) { return i * j; }

public int Div(int i, int j) { return i / j; }

….

….

….

To summarize, delegate is a type, DoSomeMath is the name of the delegate, all the Add, Sub, Mul, Div methods would qualify to be the arguments of a parameter named math below

InvokeDelegate(DoSomeMath math)
{
math.Invoke(10, 20);
}

Now, that we know how to declare a delegate, and pass a method to it, what’s the point if don’t invoke the method that was passed as an argument? Now, stay with me as I will show you an example of how you could invoke a delegate. Well, you know enough is enough, I tried by best to get a grip on delegates, and that’s how I understood it.

Remember the steps involved,

  1. Create a delegate type
  2. Create methods matching the delegate
  3. Finally, invoke the delegate

What I have seem to have grasped, is that the step 2, was some sort of overhead for developers and Microsoft in it’s C# compiler added anonymous delegates, and later lambda expressions to save some development time by introducing a new syntax – in the industrial parlance, syntax sugar as they call it.

C# delegate syntax

Let’s dive in to C#, and try creating a delegate that seems to incorporate a common real time need. I want to write a little method named PrintAllFiles and make it accept a directory location, and a filter condition. The parameter named condition is special here, because it is delegate type. Lets create that.

private delegate bool FileFilterDelegate(FileInfo file);
 

The FileFilterDelegate is capable of accepting any method that accepts a FileInfo object and returns a bool. So the two methods below qualify to be our arguments since they both accept a FileInfo parameter and return a bool.

private static bool SmallFileFilter(FileInfo fi)
{
return fi.Length < 100;
} private static bool LargeFileFilter(FileInfo fi)
{
return fi.Length > 1000000;
}

Now, lets write the PrintAllFiles method

private static void PrintAllFiles(string path, FileFilterDelegate condition)
{
FileInfo[] files = new DirectoryInfo(path).GetFiles();
foreach (var item in files)
{
if (condition(item))
{
Console.WriteLine("File: {0} \tSize: {1}", item.FullName, item.Length);
}
}
DisplayMethodFooter();
}

Alright, where am I calling the delegate? it is right inside the if condition. item is of the type FileInfo, then I call the method that is passed as an argument (it could be SmallFileFilter, or LargeFileFilter) with an argument named item.

I guess, the benefit of programming with delegates this way is pretty clear. I have the flexibility of defining as many methods as I want, but my PrintAllFiles does not change. I could write another filter tomorrow, as long as it returns a bool and accepts an FileInfo object, I would be able to pass it to my PrintAllFiles method.

Now, we created a delegate, we wrote methods with names SmallFileFilter and LargeFileFilter, and then we invoked it. Couple of options here:

  • condition(item) would Invoke the method passed as an argument
  • condition.Invoke(item) would Invoke the method passed as an argument, just as the previous one did
  • condition.BeginInvoke(item) would Invoke the method passed as an argument in an asynchronous manner.

The essence here is the PrintAllFiles method that accepts a FileFilterDelegate. We could call it like below, by passing it the methods that match the FileFilterDelegate definition.

DisplayHeader("//traditional way - create a method accepting and returning the same types as the delegate");
PrintAllFiles(@"C:\", SmallFileFilter);
PrintAllFiles(@"C:\", LargeFileFilter);

Using Anonymous Delegates

We created methods named SmallFileFilter and LargeFileFilter, for a reason being that’s how we were accustomed to write a method. Think of some cool names and name the method that way, so I could use that name and call it over and over, or pass it as a delegate argument over and over.

But instead, it I wanted a filter for one-off usage, I really don’t want to create a method and give it a name. I could simply write a method on the fly without a name. how’d I do that? Well, we are talking about Anonymous delegates already.

See the code below, it is just a method right there, without a name. All that is missing there is private static bool SmallFileFilter, private static bool LargeFileFilter; that are essentially replaced by the keyword delegate.

DisplayHeader("//using Anonymous delegates - methods with no name");
PrintAllFiles(@"C:\", delegate(FileInfo fi) { return fi.Length < 100; });
PrintAllFiles(@"C:\", delegate(FileInfo fi) { return fi.Length > 1000000; });

Now I don’t really need a method with a name. I could just write a method without a name on the fly and that would be considered an anonymous delegate if we prefixed it with the delegate keyword. Point to understand is we didn’t really eliminate the need to write methods, we just eliminated the need to name them.

Lets do some lambdas

We know how to write a method without a name, a method that was supposed to be passed as an argument. We did that by using the delegate keyword. Now as they wanted to make things simple and simple everyday, they made us put a lambda ( => ) instead of the delegate keyword.

DisplayHeader("//using lambda - the delegate keyword is not needed anymore");
PrintAllFiles(@"C:\", (FileInfo fi) => { return fi.Length < 100; });
PrintAllFiles(@"C:\", (FileInfo fi) => { return fi.Length > 1000000; });

That’s it! We saw how to create a delegate, how to write a method matching the delegate, how to pass it as an argument, how to invoke it.

..and there was this need to not name a method.. we preferred Anonymous Delegates

….then saw how to oust anonymous delegate with a lambda expression.

I guess I have stayed and not swayed from the title of the post. Although, these are not the only uses of lambda, this is one way, you can get a grip on if your lambda highway is slippery yet. Other great articles about lambda expressions, and it’s uses are below. If they are in too detail, a glance would do, that’s what I did.

http://stackoverflow.com/questions/167343/c-sharp-lambda-expression-why-should-i-use-this

http://www.codeproject.com/Articles/17575/Lambda-Expressions-and-Expression-Trees-An-Introdu

http://www.codeproject.com/Articles/24255/Exploring-Lambda-Expression-in-C

http://msdn.microsoft.com/en-us/magazine/cc163362.aspx

Complete source code to test the samples and play with it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; namespace EvolutionOfLamdaExpression2
{
class Program
{
static void Main(string[] args)
{
DisplayHeader("//traditional way - create a method accepting and returning the same types as the delegate");
PrintAllFiles(@"C:\", SmallFileFilter);
PrintAllFiles(@"C:\", LargeFileFilter); DisplayHeader("//using Anonymous delegates - methods with no name");
PrintAllFiles(@"C:\", delegate(FileInfo fi) { return fi.Length < ; });
PrintAllFiles(@"C:\", delegate(FileInfo fi) { return fi.Length > ; }); DisplayHeader("//using lambda - the delegate keyword is not needed anymore");
PrintAllFiles(@"C:\", (FileInfo fi) => { return fi.Length < ; });
PrintAllFiles(@"C:\", (FileInfo fi) => { return fi.Length > ; }); DisplayHeader("//using Func delegate - use the inbuilt templatized delegates");
PrintAllFiles2(@"C:\", (FileInfo fi) => { return fi.Length < ; });
PrintAllFiles2(@"C:\", (FileInfo fi) => { return fi.Length > ; });
} private delegate bool FileFilterDelegate(FileInfo file); private static bool SmallFileFilter(FileInfo fi)
{
return fi.Length < ;
} private static bool LargeFileFilter(FileInfo fi)
{
return fi.Length > ;
} private static void PrintAllFiles(string path)
{
foreach (var item in new DirectoryInfo(path).GetFiles())
{
Console.WriteLine("File: {0} \tSize: {1}", item.FullName, item.Length);
}
DisplayMethodFooter();
} private static void PrintAllFiles(string path, FileFilterDelegate condition)
{
FileInfo[] files = new DirectoryInfo(path).GetFiles();
foreach (var item in files)
{
if (condition(item))
{
Console.WriteLine("File: {0} \tSize: {1}", item.FullName, item.Length);
}
}
DisplayMethodFooter();
} private static void PrintAllFiles2(string path, Func<FileInfo, bool> condition)
{
FileInfo[] files = new DirectoryInfo(path).GetFiles();
foreach (var item in files)
{
if (condition(item))
{
Console.WriteLine("File: {0} \tSize: {1}", item.FullName, item.Length);
}
}
DisplayMethodFooter();
} private static void DisplayHeader(string p)
{
Console.WriteLine("------------------------------------------------------------------------------------------");
Console.WriteLine(p);
Console.WriteLine("------------------------------------------------------------------------------------------");
} private static void DisplayMethodFooter()
{
Console.WriteLine("EOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOMEOM");
} }
}

From delegates to lambdas z的更多相关文章

  1. 【Python】使用torrentParser1.03对多文件torrent的分析结果

    Your environment has been set up for using Node.js 8.5.0 (x64) and npm. C:\Users\horn1>cd C:\User ...

  2. 【Xamarin笔记】Events, Protocols and Delegates

    Events, Protocols and Delegates   事件.协议和委托 This article presents the key iOS technologies used to re ...

  3. F​l​e​x​4​+​s​p​r​i​n​g​+​h​i​b​e​r​n​a​t​e​+​B​l​a​z​e​D​S​整合案例

    http://wenku.baidu.com/link?url=7v5xAyD2nvChQRT60QewpvAASFHMZNvD0OxX11OASYvae8jbVNsr5I000TwwYOlChzq0 ...

  4. Android立体旋转动画实现与封装(支持以X、Y、Z三个轴为轴心旋转)

    本文主要介绍Android立体旋转动画,或者3D旋转,下图是我自己实现的一个界面 立体旋转分为以下三种: 1. 以X轴为轴心旋转 2. 以Y轴为轴心旋转 3. 以Z轴为轴心旋转--这种等价于andro ...

  5. Z字形扫描(201412-2)

    问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的4×4的矩阵, 1 5 3 9 3 7 5 ...

  6. 【IOS】将一组包含中文的数据按照#ABC...Z✿分组

    上一篇文章[IOS]模仿windowsphone列表索引控件YFMetroListBox里面 我们一步步的实现了WindowsPhone风格的索引. 但是有没有发现,如果你要实现按照字母排序,你还得自 ...

  7. Java 压缩/ 解压 .Z 文件

    1.问题描述 公司项目有需要用 JAVA 解压 .z文件. .z 是 unix 系统常见的压缩文件. 2.源码 import com.chilkatsoft.CkUnixCompress; impor ...

  8. 中文编程语言Z语言开源正式开源!!!

    (Z语言基于.NET环境,源码中有很多高技术的代码,让更多的人知道对大家有会有很好的帮助,请管理员一点要批准放在首页) 本人实现的中文编程语言Z语言现在正式开源,采用LGPL协议. 编译器核心的网址为 ...

  9. 开发该选择Blocks还是Delegates

    前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中在stablekernel找到了这篇文章,文中作者不仅仅是给出了解决方案,更值得我们深思的是作者独特 ...

随机推荐

  1. zoj 3471 Most Powerful

    题目链接:zoj 3471 Most Powerful  作者:jostree 转载请说明出处 很经典的状态dp,使用i的二进制位表示粒子的状态,0表示存在,1表示不存在.dp[i]表示在状态i的情况 ...

  2. centos 6.5 x64编译有python的vim7.4

    wget ftp://ftp.vim.org/pub/vim/extra/vim-7.2-extra.tar.gzwget ftp://ftp.vim.org/pub/vim/extra/vim-7. ...

  3. Oracle 自连接 / 外连接 / 子查询

    --连接查询的三种格式 select ename, deptno,dname from emp natural join dept; select ename, deptno,dname from e ...

  4. ASP.NET DataList嵌套实现评论效果

    问题: Datalist1显示say这个表的数据 然后想在Datalist1中嵌套一个Datalist2用于显示对应的评论表2的 sayID对应表1的id,若表2中找不到对应sayId则在对应的Dat ...

  5. C# Activex开发、打包、签名、发布

    一.前言      最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠HTML是无法实现了,因此必须借用Activex来实现.由于本人主要擅长C#,自然本文给出了用C# ...

  6. CSS浮动特性总结

    1.假设现在CSS中没有浮动(float)属性,那么会变成一个什么样子.我们会发现,目前流行采用浮动方法实现的无论是分栏布局,还是列表排列我们都可以用其他一些CSS属性(不考虑table)代替实现,唯 ...

  7. OSG Win7 + VS2015 编译

    1. 准备 建立目标树 OpenSceneGraph-VERSION (VERSION替换为版本号) OpenSceneGraph-VERSION\3rdParty (把依赖库放在此目录) http: ...

  8. hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...

  9. 2014年度辛星css教程夏季版第五节

    本小节我们讲解css中的”盒模型“,即”box model“,它通常用于在布局的时候使用,这个”盒模型“也有人成为”框模型“,其实原理都一样,它的大致原理是这样的,它把一个HTML元素分为了这么几个部 ...

  10. Oracle存储过程创建及调用(转)

    在大型数据库系统中,有两个很重要作用的功能,那就是存储过程和触发器.在数据库系统中无论是存储过程还是触发器,都是通过SQL 语句和控制流程语句的集合来完成的.相对来说,数据库系统中的触发器也是一种存储 ...