委托和lambda表达式,Action和Func

转自博客园(殉殇)html

委托和lambda表达式,Action和Func

一、为何要用委托

咱们为何要有委托?任何东西存在即合理,不合理的也会被时间淘汰掉,委托既然存在确定有存在的必要,咱们来看一下何时能够用到委托。算法

接下来咱们有个需求,就是调用一个方法,取出1-1000个数字中全部是10的倍数的数字c#

public static List<int> GetNum() {
    List<int\> lst = new List<int>(); //这个算法是最简陋的,可是举这个例子是最合适的
    for (int i = 1; i < 1000; i++)
    { if (i%10==0) {
            lst.Add(i);
        }
    } return lst;
}

这个很好写,可是若是有一天,咱们的需求变了,想取出1-1000个数字中全部是8的倍数的数字,那咱们应该怎么写?是否是只要将if里面的条件改成i%8==0就好了,可是有一点变更的话就修改方法,说明这个方法写的并很差,若是方法很复杂的话修改也很艰难。可能有人会说在添加一个获取是8的倍数的方法,这样的话会增长数据冗余,也就是重复的内容。函数

若是咱们能够传递方法的话,只要传过来一个(有一个参数为int类型返回值为Boolean类型的方法),这个问题将不是问题指针

public static List<int> GetNum(有一个int类型的参数返回值为Boolean类型的方法) {
    List<int\> lst = new List<int>();
    for (int i = 1; i < 1000; i++)
    { if (有一个int类型的参数返回值为Boolean类型的方法) {
            lst.Add(i);
        }
    } return lst;
}

是否是咱们将想要获取什么样的数字这个操做来交给了调用者,不管调用者想获取1-1000之内什么样的数字均可以完成。可是这个方法的前提就是能够传递方法,这个时候咱们就须要用到委托了。code

二、委托如何使用

委托其实就是一个可以指向方法的 指针,定义了一个委托就是定义了一个 类型

首先咱们先来定义一个委托,也就是定义一个类型htm

//访问修饰符  委托关键字  方法的返回值类型  要定义的类型名(参数1,参数2.....);
public delegate Boolean DelegateFunc(int x);

委托定义好了,也就是说咱们已经定义好了一个DelegateFunc类型,这个类型的使用方法就和public class DelegateFunc{}写了一个类是同样的,由于都是定义了一个类型,既然你们都是类型,那用法确定都是同样的,咱们先来看一下声明普通的类型是如何声明的对象

//类型 变量名 = 实例化一个Object类型的对象(构造函数有无参数)
Object obj = new Object();

而DelegateFunc既然也是咱们定义好的一个类型,那用法天然同样(由于构造函数须要参数,因此下面这样写是不对的,没有传入参数)blog

//类型       变量名 = 实例化一个DelegateFunc类型的对象(构造函数有无参数)
DelegateFunc func = new DelegateFunc();

委托是一个可以指向方法的指针,而它的构造函数就是须要一个方法,接着咱们来定义一个返回值为Boolean,能接收一个int类型参数的方法继承

//至关于方案1
public static Boolean Condition1(int i)
{ //模拟复杂的操做 至关于return i%10==0;
    int x = i % 10; if (i % 10 == 0)
    { return true;
    } else { return false;
    }
}

定义好了方法咱们再来实例化一个DelegateFunc类型的对象

//构造函数放入方法的话不须要带(),带()的话是调用
DelegateFunc func = new DelegateFunc(Condition1);

下面看一下下面这种声明委托类型的方式

//一样都是类型Object类型能够这样写 //由于String最终是继承自Object,而且String能够默认转换为Object
Object obj = "obj"; //而DelegateFunc也能够经过这种方式赋值,这说明Condition1能够默认转换为委托类型
DelegateFunc func = Condition1;

实例化完成以后func变量就会指向Condition1方法,调用方式以下

//调用委托类型的对象和调用普通的方法是同样的
func(10);

而后咱们把刚才写的GetNum方法修改成以下的样子,参数为接收一个DelegateFunc类型的参数,也就是委托类型

public static List<int> GetNum(DelegateFunc func)
{
    List<int\> lst = new List<int>();
    for (int i = 1; i < 1000; i++)
    { //调用传过来的方法,根据调用者传过来的方法拿到想要的数字
        if (func(i))
        {
            lst.Add(i);
        }
    } return lst;
}

在Main方法中调用GetNum方法

//声明委托
DelegateFunc func = new DelegateFunc(Condition1); //调用方法
List<int\> lst = GetNum(func); //也能够直接调用,由于都会默认转换 //List<int> lst = GetNum(Condition1); //输出
foreach (int item in lst)
{
    Console.WriteLine(item);
}

输出

若是咱们有新的方案的话,只须要在新建一个方案,而后传入方法中,好比咱们还看刚才那个求1-1000之内8的倍数,咱们只须要声明一个新的方案

//声明一个新的方案2
public static Boolean Condition2(int i) { //一样模拟复杂的操做 至关于return i%8==0;
    int x = i % 8; if (i % 8 == 0)
    { return true;
    } else { return false;
    }
}

而后和刚才同样,声明一个委托就行,传入GetNum就行。

不过咱们看一下,虽然已经比较简化代码了,可是写起来仍是很麻烦,而后咱们来看一下lambda表达式

三、lambda表达式

首先lambda表达式只是方法的一种写法!lambda声明的方法是匿名方法,它和委托并非绑死的,这是两个东西,可是lambda表达式和委托结合使用是很是常见的!

 看一下lambda表达式的语法,也就是函数的另外一种写法

//能够这样写 //DelegateFunc func = new DelegateFunc((i) => //{ // return i % 8 == 0; //}); //也能够这样 不进行new DelegateFunc操做,由于会默认转换 //若是有多句的话,这样写每一句经过分号隔开
DelegateFunc func = (i) => { return i % 8 == 0; }; //若是只有单句 不用写return    默认reuturn   i%8==0 这一句计算出来的值
func = (i) => i % 8 == 0; //若是只有一个参数   多个参数的话要(i,j,....)这样写
func = i => i % 8 == 0;

除此以外lambda也能够用来声明方法,貌似只能写一句,,,,

//无返回值
public static void HelloWord() => Console.WriteLine("Hello Word!"); //有返回值
public static String GetHelloWord() => "Hello Word!";

有了lambd咱们再来调用GetNum,就会变得很是方便

//8的倍数
List<int\> lst = GetNum((i) => i % 8 == 0); //10的倍数
lst = GetNum(i => i % 10 == 0); //20的倍数
lst = GetNum(i => i % 20 == 0);

四、Action和Func

Action和Func是微软已经定义好的的两种委托类型,区别是Action是没有返回值的,而Func是须要返回值的

Action使用方法

//无参数
Action action1 = () => Console.WriteLine("action"); //有参数的话调用Action<T>
Action<int\> action2 = (i) => Console.WriteLine(i); //多个参数就在生命的时候<T,T,T>
Action<int,string\> action3 = (i, str) => Console.WriteLine(i+"\\t"+str); //调用
action1();
action2(10);
action3(10,"s");

运行结果:

Func使用方法

//Func是没有Func类型的,只有Func<T>类型
Func<string\> func1 = () => "func"; //若是须要参数 Func<T,T,T> //最后一个T类型为返回值类型,前面的全都为参数的类型!!!
Func<string, int\> func2 = (i) => int.Parse(i); //若是有多个参数     最后一个T类型为返回值类型,前面的全都为参数的类型!!!
Func<int, string, int\> func3 = (i, str) => int.Parse(i + str); //调用
Console.WriteLine(func1());
Console.WriteLine(func2("123"));
Console.WriteLine(func3(1,"23"));

运行结果

相关文章
相关标签/搜索