委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。

与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用

一、自定义委托类型

1.语法结构:访问修饰符 delegate 返回类型 委托类型名称(参数列表);

例如:

// 声明一个委托类型,两个参数均为int类型,返回值为int类型
public delegate int Calc(int a, int b);
自定义的委托可以不带参数,也可以没有返回值。 接下来我们看一个例子怎么使用委托

1.方法引用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 委托
{
class Program
{
// 声明一个委托类型,两个参数均为int类型,返回值为int类型
public delegate int Calc(int a, int b); // 定义和委托签名一致的方法(参数类型和个数,返回值类型均一致)
static int Add(int a, int b)
{
return a + b;
} static int Sub(int a, int b)
{
return a - b;
} static int Multi(int a, int b)
{
return a * b;
} static int Divis(int a, int b)
{
if (b == )
{
throw new Exception("除数不能为0!");
} return a / b;
} static void Main(string[] args)
{
Console.WriteLine("请输入第一个数:");
int a = int.Parse(Console.ReadLine()); Console.WriteLine("请输入第二个数:");
int b = int.Parse(Console.ReadLine()); // 定义一个Calc委托类型的变量,把和该委托签名一致的Add方法的引用赋值给变量
Calc method = Add;
Console.WriteLine("加法运算:{0}+{1}={2}", a, b, method(a, b)); method = Sub;
Console.WriteLine("减法法运算:{0}-{1}={2}", a, b, method(a, b)); method = Multi;
Console.WriteLine("乘法运算:{0}×{1}={2}", a, b, method(a, b)); method = Divis;
Console.WriteLine("除法运算:{0}÷{1}={2}", a, b, method(a, b)); Console.ReadKey();
}
}
}

(1)方法引用

2.匿名方法

给上述委托变量赋值时,必须先定义好一个和委托签名一致的方法。使用匿名方法,你就无需先定义好那些方法,直接通过delegate语法给委托变量赋值。

匿名方法的结构:delegate(参数列表){函数体};

例如:

Calc method = delegate(int x, int y)
{
return x + y;
}; 使用匿名方法重新实现上述例子:
(2)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 匿名方法
{
class Program
{
// 声明一个委托类型,两个参数均为int类型,返回值为int类型
delegate int Calc(int a, int b); static void Main(string[] args)
{
Console.WriteLine("请输入第一个数:");
int a = int.Parse(Console.ReadLine()); Console.WriteLine("请输入第二个数:");
int b = int.Parse(Console.ReadLine()); // 定义一个Calc委托类型的变量
Calc method = delegate(int x, int y)
{
return x + y;
};
Console.WriteLine("加法运算:{0}+{1}={2}", a, b, method(a, b)); method = delegate(int x, int y)
{
return x - y;
};
Console.WriteLine("减法法运算:{0}-{1}={2}", a, b, method(a, b)); method = delegate(int x, int y)
{
return x * y;
};
Console.WriteLine("乘法运算:{0}×{1}={2}", a, b, method(a, b)); method = delegate(int x, int y)
{
return x / y;
};
Console.WriteLine("除法运算:{0}÷{1}={2}", a, b, method(a, b)); Console.ReadKey();
}
}
}

匿名方法

反编译生成的exe文件,你会发现编译器自动帮你生成了4个与自定义委托类型签名一致的方法,并且Main方法中的匿名方法变成了Lamdba表达式的形式,如图:

3.Lamdba表达式

Lamdba表达式其实就是一种语法糖,让你更能简洁的编写代码。

其语法结构:(参数列表)=>{函数体};

用Lamdba表达式实现上述例子:

(3)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Lamdba表达式
{
class Program
{
// 声明一个委托类型,两个参数均为int类型,返回值为int类型
delegate int Calc(int a, int b); static void Main(string[] args)
{
Console.WriteLine("请输入第一个数:");
int a = int.Parse(Console.ReadLine()); Console.WriteLine("请输入第二个数:");
int b = int.Parse(Console.ReadLine()); // 定义一个Calc委托类型的变量
Calc method = (x, y) => { return x + y; };
Console.WriteLine("加法运算:{0}+{1}={2}", a, b, method(a, b)); method = (x, y) => x - y; // 也可以这样写
Console.WriteLine("减法法运算:{0}-{1}={2}", a, b, method(a, b)); method = (x, y) => { return x * y; };
Console.WriteLine("乘法运算:{0}×{1}={2}", a, b, method(a, b)); method = (x, y) => { return x / y; };
Console.WriteLine("除法运算:{0}÷{1}={2}", a, b, method(a, b)); Console.ReadKey();
}
}
}

Lamdba表达式

你也可以反编译生成的exe文件,你会发现结果与匿名方法反编译的效果一样。

二、.Net自带的委托类型

1.Func委托类型

Func是有返回值的泛型委托,可以没有参数,但最多只有16个参数,并且必须要有返回值,不能为void类型。如图:

Func<int, int, int> // 第一,二个参数为int类型,返回值为int类型
Func<string, string, bool> // 第一,二个参数string类型,返回值为bool类型
Func<int, string, decimal> // 第一个参数为int类型,第二个参数为string类型,返回值为decimal类型

同自定义的委托类型一样,你可以为Func委托变量赋值为方法引用,匿名方法或者Lamdba表达式:

(1)方法引用 

(2)匿名方法

(3)Lamdba表达式

2.Action委托类型 
Action是没有返回值的泛型委托,可以没有参数,但最多只有16个参数,返回值为void类型。如图:

直接看例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Action委托类型
{
class Program
{
static void Main(string[] args)
{
Action<string, string> method = (s1, s2) => { Console.WriteLine(s1 + s2); }; method("1+1=", "2");
Console.ReadKey();
}
}
}

3.Predicate委托类型 
Predicate是只有一个参数,且返回值为bool类型的泛型委托。

// 摘要:
// 表示定义一组条件并确定指定对象是否符合这些条件的方法。
//
// 参数:
// obj:
// 要按照由此委托表示的方法中定义的条件进行比较的对象。
//
// 类型参数:
// T:
// 要比较的对象的类型。
//
// 返回结果:
// 如果 obj 符合由此委托表示的方法中定义的条件,则为 true;否则为 false。
public delegate bool Predicate<in T>(T obj);

直接看例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Predicate委托类型
{
class Program
{
static void Main(string[] args)
{
Predicate<int> method = (x) => { return x > 3; }; Console.WriteLine(method(4));// 输出:True
Console.ReadKey();
}
}
}

三、综合应用

这些自带的委托类型在泛型集合中使用的比较多,如:

接下来再看一个综合例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 运用
{
class Program
{
static void Main(string[] args)
{
List<Student> list = new List<Student>
{
new Student{Name="张三",Age=},
new Student{Name="李四",Age=},
new Student{Name="王五",Age=},
new Student{Name="马六",Age=},
new Student{Name="李七",Age=}
}; // Func委托类型
List<Student> list2 = list.Where(item => item.Age < ).ToList();
foreach (Student stu in list2)
{
Console.WriteLine("姓名:{0},年龄:{1}。", stu.Name, stu.Age);
}
Console.WriteLine("============================"); // Action委托类型
list.ForEach((s) => { Console.WriteLine("姓名:{0},年龄:{1}。", s.Name, s.Age); });
Console.WriteLine("============================"); // Predicate委托类型
Student student = list.Find(item => item.Age > );
Console.WriteLine("姓名:{0},年龄:{1}。", student.Name, student.Age);
Console.WriteLine("============================"); Console.ReadKey();
}
} class Student
{
public string Name { get; set; } public int Age { get; set; }
}
}

运行结果: 

原文:http://www.tuicool.com/articles/maYBRb

自定义委托类型 - .Net自带委托类型的更多相关文章

  1. 泛型 System.Collections.Generic及泛型继承、运算符、结构、接口、方法、委托、事件、可空类型等

    一.定义泛型类 void Main() { //实例化泛型类时,才指定具体的类型 MyGenericClass<); Console.WriteLine(MyGeneri.InnerT1Obje ...

  2. .Net自带的委托类型—Func,Action 和 Predicate

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递. 与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用. 一.自定义委托类型 1.语法结构:访问修 ...

  3. C#简单问题,不简单的原理:不能局部定义自定义类型(不含匿名类型)

    今天在进行代码测试时发现,尝试在一个方法中定义一个委托,注意是定义一个委托,而不是声明一个委托变量,在编写的时候没有报错,VS也能智能提示,但在编译时却报语法不完整,缺少方括号,但实际查询并没有缺少, ...

  4. 事件,使用.net自带委托EventHandler

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. 《Go语言实战》Go 类型:基本类型、引用类型、结构类型、自定义类型

    Go 语言是一种静态类型的编程语言,所以在编译器进行编译的时候,就要知道每个值的类型,这样编译器就知道要为这个值分配多少内存,并且知道这段分配的内存表示什么. 提前知道值的类型的好处有很多,比如编译器 ...

  6. 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)

    1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ...

  7. Mybatis中使用自定义的类型处理器处理枚举enum类型

    知识点:在使用Mybatis的框架中,使用自定义的类型处理器处理枚举enum类型 应用:利用枚举类,处理字段有限,可以用状态码,代替的字段,本实例,给员工状态字段设置了一个枚举类 状态码,直接赋值给对 ...

  8. 026 Android 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+读取内存空间、手机进程信息+常驻悬浮框

    1.目标效果 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+常驻悬浮框 2.页面布局文件 (1)activity_process_manager.xml <?xml ...

  9. 带Boolean类型的参数的接口用postman测试时传参问题

    带Boolean类型的参数的接口用postman测试时传参问题 @Data public class ATest { private Boolean isCommit; } postman 测试时传参 ...

随机推荐

  1. IE浏览器版本判断 HTML代码

    <!--[if IE 6.0]> <div id="noie6" style="z-index: 20002;border: 1px solid #F7 ...

  2. ProgressBar---进度条

    最近在处理标题进度条时,耗费了一些时间,现在总结一下ProgressBar的相关知识,有不对的地方请大神们批评指正! 进度条主要有以下三种: 1.对话框进度条 2.标题进度条 注意:requestWi ...

  3. javascript中的预编译问题

    Js作为脚本语言,可以不需要编译直接运行,但遇到类似变量或者函数同名,预编译方面的知识可以帮助我们更好解决问题. 示例: 这是一段js中普通的函数调用代码 <script>1.    // ...

  4. angularjs $broadcast $emit $on 事件触发controller间的值传递

    如何在作用域之间通信呢? 1.创建一个单例服务,然后通过这个服务处理所有子作用域的通信. 2.通过作用域中的事件处理通信.但是这种方法有一些限制:例如,你并不能广泛的将事件传播到所有监控的作用域中.你 ...

  5. 利用yeoman快速搭建React+webpack+es6脚手架

    自从前后端开始分离之后,前端项目工程化也显得越来越重要了,之前写过一篇搭建基于Angular+Requirejs+Grunt的前端项目教程,有兴趣的可以点这里去看 但是有些项目可以使用这种方式,但有些 ...

  6. angular1.x的简单介绍 (一)

    angular1.x作为经典的mvc框架,可以创建能够复用的组件,也可进行双向数据绑定.国内的vue.js/avaloon.js都是同类型的框架.适合使用angularjs的项目有大型信息化管理系统: ...

  7. js实现返回顶部功能的解决方案

    很多网站上都有返回顶部的效果,主要有如下几种解决方案. 1.纯js,无动画版本 window.scrollTo(x-coord, y-coord); window.scrollTo(0,0); 2.纯 ...

  8. ubantu16.04+mxnet +opencv+cuda8.0 环境搭建

    ubantu16.04+mxnet +opencv+cuda8.0 环境搭建 建议:环境搭建完成之后,不要更新系统(内核) 转载请注明出处: 微微苏荷 一 我的安装环境 系统:ubuntu16.04 ...

  9. AndroidStudio导入项目出现Your project path contains non-ASCII characters错误

    Your project path contains non-ASCII characters. This will most likely cause the build to fail on Wi ...

  10. 第三十一篇:SOUI布局之相对于特定兄弟窗口

    SOUI中通过pos的标志如:[, {, }, ],这4个标志可以相对于前一个及后一个兄弟窗口,但是有时候希望相对于不是前后窗口的兄弟窗口,比如一个通过一个中心窗口同时定义它的上下左右4个窗口,这个时 ...