C#中的委托和Lambda表达式

今天看Curator源码时发现其请求ZooKeeper集群时内部封装了重试机制,代码如下:

Stat resultStat = RetryLoop.callWithRetry
        (
            client.getZookeeperClient(),
            new Callable<Stat>()
            {
                @Override
                public Stat call() throws Exception
                {
                    return client.getZooKeeper().setData(path, data, version);
                }
            }
        );
public static<T> T callWithRetry(CuratorZookeeperClient client, Callable<T> proc) throws Exception
    {
        T result = null;
        RetryLoop retryLoop = client.newRetryLoop();
        while ( retryLoop.shouldContinue() )
        {
            try
            {
                client.internalBlockUntilConnectedOrTimedOut();

                //调用带返回值的Callable方法
                result = proc.call();
                retryLoop.markComplete();
            }
            catch ( Exception e )
            {
                retryLoop.takeException(e);
            }
        }
        return result;
    }

利用Java中的Callable<T>,即带返回值T的线程这个功能来将失败时要重试的代码段传递到重试函数中进行调用。

因为我要开发C#的对应的版本,所以也需要将一段代码(请求ZooKeeper的代码)传递到这样一个具备失败重试功能的函数中运行,由于我对C#不是很熟悉,所以能想到的只有通过声明一个代理,再定义一个操作ZooKeeper的函数,将这个函数赋值给代理,将代理传递到具备重试功能的函数中。

但是这种方式势必要定义一个代理,还要显式申明一个方法赋值给代理,代码量大且不是很优雅,所以我就开始深入了解C#这方面如何实现,然后发现了C#2.0引入的匿名方法,以及C#3.0引入的用于取代匿名方法的Lambda表达式,是编写内联代码的首选。下面先提供我写的一段测试代码,可以完成我的需求,之后再讲解何谓匿名方法和Lambda表达式。

CustomDelegate.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace DelegateAndLamda
{
    delegate string CustomDelegate(string material);
}

PizzaMaker.cs:

namespace DelegateAndLamda
{
    class PizzaMaker
    {
        public static void makePizza(string material, CustomDelegate bake)
        {
            //前面有一堆固定流程,但是接下来烘烤方法不同
            string result = bake(material);
            Console.WriteLine(result);
        }
    }
}

Program.cs

namespace DelegateAndLamda
{
    class Program
    {
        public static void Main(string[] args)
        {
            //在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法
            CustomDelegate bake = new CustomDelegate(bakePizza);
            PizzaMaker.makePizza("张三的Pizza", bake);

            // C# 2.0 引入了匿名方法
            PizzaMaker.makePizza("李四的Pizza", delegate(string material)
            {
                return String.Format("将{0}烘烤成面包", material);
            } );

            //在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式
            PizzaMaker.makePizza("季义钦的Pizza", material =>
            {
                return String.Format("将{0}烘烤成意大利pizza", material);
            });
        }        

        public static string bakePizza(string material)
        {
            return String.Format("将{0}烘烤成西瓜", material);
        }
    }
}

参考网址:

委托: http://msdn.microsoft.com/zh-cn/library/900fyy8e.aspx

匿名方法: http://msdn.microsoft.com/zh-cn/library/0yw3tz5k.aspx

Lambda表达式: http://msdn.microsoft.com/zh-cn/library/bb397687.aspx

表达式树: http://msdn.microsoft.com/zh-cn/library/bb397951.aspx

Linq查询: http://msdn.microsoft.com/zh-cn/library/bb397906.aspx

时间: 2024-10-08 10:30:27

C#中的委托和Lambda表达式的相关文章

maven编译报错 -source 1.5 中不支持 lambda 表达式(转)

原文链接:http://blog.csdn.net/kai161/article/details/50379418 在用maven编译项目是由于项目中用了jdk 1.8, 编译是报错  -source 1.5 中不支持 lambda 表达式,Google找到这篇解决方案,记录一下: 编译时报如下错误: [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [

maven编译报错 -source 1.7 中不支持 lambda 表达式

Maven项目编译失败: [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [ERROR] /opt/ihome/jenkins/jobs/dev-aladdin-order/workspace/aladdin-order-intf/src/main/java/com/ihomefnt/aladdin/common/utils/RemoteUtil.ja

IDEA中打包Spark项目提示Error:(16, 48) java: -source 1.5 中不支持 lambda 表达式

在idea中新建了一Spark的项目,在做项目的编译打包的时候,提示如下错误信息: Error:(16, 48) java: -source 1.5 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式) 解决方法是: 第一步: File --> Project Stucture 选择项目设置Lanugage level, 如下图所示 第二步: File --> Settings --> Compiler --> Java Compi

maven编译报错 -source 1.5 中不支持 lambda 表达式

ji与基于maven的工程java应用程序非web应用的 参考这个https://www.cnblogs.com/softidea/p/6256543.html 但是java应用里边是没有这个配置的,然后我打开一个javaweb应用,发现里边有,抱着试一试的态度 直接随便找个工程的build部分拆过来,贴到pom.xml中就行了然后版本号改了 <build> <plugins> <plugin> <groupId>org.apache.maven.plugi

(转)C#中的委托,匿名方法和Lambda表达式

简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=5.答案是6个First不仅被编译,并都获得正确答案,且他们的结果一样.如果你对此感到困惑,那么请继续看这篇文章. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Customer {     public int ID { get; set; }     p

写的非常好的文章 C#中的委托,匿名方法和Lambda表达式

简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=5.答案是6个First不仅被编译,并都获得正确答案,且他们的结果一样.如果你对此感到困惑,那么请继续看这篇文章. class Customer { public int ID { get; set; } public static bool Test(Customer x) { return x.ID == 5; }

C#中的Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

boost在lambda表达式中调用占位符参数的成员函数的方法

boost中提供了lambda表达式的用法,但是lambda表达式的功能还不是很强大,在其中只能对lambda的占位符参数_1等使用最基本的操作符,如+-*/,可是很多时候如果传入的占位符参数是一个对象指针的话,我们可能想要调用这个类的成员函数. 我在开发中遇到了这个问题,需要在stl的算法中传入一个函数来调用对象的比较函数,因为感觉这样太麻烦,还需要重新定义一个函数,所以想起了lambda表达式,c++11的lambda表达式我倒是没试过,可是受项目开发环境所限,只能选择boost.但是我用的

在Android Studio中使用Lambda表达式

Lambda表达式是Java 8的一个新特性,可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂.Lambda表达式同时还提升了对集合的迭代.遍历.过滤数据的操作.那么在Android Studio中如何使用lambda表达式呢? 项目使用的jdk要为jdk 8或更高版本 修改build.gradle文件,enable jack和设置sourceCompatibility,targetCompatibility为jdk 8 defaultConfig { ... jackOpt