自定义委托类型 - .Net自带委托类型

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

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

一、自定义委托类型

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 == 0)
            {
                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=24},
                new Student{Name="李四",Age=32},
                new Student{Name="王五",Age=36},
                new Student{Name="马六",Age=45},
                new Student{Name="李七",Age=28}
            };

            // Func委托类型
            List<Student> list2 = list.Where(item => item.Age < 30).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 > 40);
            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

时间: 2024-07-30 13:42:35

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

C#控制台基础 返回类型为void的 int 类型 参数委托与匿名函数

1 code 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace ConsoleApplication2 8 { 9 //返回类型为void的 int 类型 参数委托 10 public delegate void MyFirst(int num); 11 class P

【续】使用泛型编写通用的C#预处理类型转换方法(使用委托提高性能)

优化后的代码: public static class Converter { /// <summary> /// 转换为其他继承IConvertible的类型 /// </summary> /// <typeparam name="T">转换的类型</typeparam> /// <param name="value">要转换的值</param> /// <param name=&quo

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

Go 语言是一种静态类型的编程语言,所以在编译器进行编译的时候,就要知道每个值的类型,这样编译器就知道要为这个值分配多少内存,并且知道这段分配的内存表示什么. 提前知道值的类型的好处有很多,比如编译器可以合理的使用这些值,可以进一步优化代码,提高执行的效率,减少 bug 等等. 基本类型 基本类型是 Go 语言自带的类型,比如 数值.浮点.字符串.布尔.数组 及 错误 类型,他们本质上是原始类型,也就是不可改变的,所以对他们进行操作,一般都会返回一个新创建的值,所以把这些值传递给函数时,其实传递

C# 使用linq处理返回带datetime类型数据 json显示/date(xxxxx)/

以前做项目一直遇到带数据库里面带datetime类型数据 返回到前台会变成时间戳 这显然不是我们想要的 于是我在最初的项目中 选择在前端JS格式化date(xxxx)形式的方式处理 现在想来有点蠢 今天灵机一动 想到是不是可以在服务端就把datetime转成string返回到 结果就有了此文 服务端: 1 DataGetEntities context = new DataGetEntities(); 2 var queryTyphoon = context.T_TyphoonPaths.Whe

C# 语法 ( 框架自带委托和异步 )

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 异步线程 { class AsyncHronous { private int i = 0; public void Show() { for (int i = 0; i < 5; i++) { //系统自带的委托(有参数无返回值,有参数有返回值) Actio

委托学习笔记1:委托的基本使用

一.引子 在正式说委托前,我先给一个例子,然后引出后面要说的委托. 很简单,就是一个机器人打招呼的. 代码清单1.1: class Robot { public void GreetByChinese(string name) { Console.WriteLine("你好," + name + "!"); } public void GreetByEnglish(string name) { Console.WriteLine("Hello,"

CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1; 等价于: int a = 1; 这种语法不仅增强了代码的可读性,其生成的IL代码与使用System.Int32时生成的IL代码是完全一致的. 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到Framework类库(FCL)中存在的类型.如C#中,int直接映射

C# 委托链、多路广播委托

委托链.多路广播委托:也就是把多个委托链接在一起,我们把链接了多个方法的委托称为委托链或多路广播委托 例: 1 class HelloWorld 2 { 3 //定义委托类型 4 delegate void DelegationChain(); 5 static void Main(string[] args) 6 { 7 //用静态方法来实例委托 8 DelegationChain mydelegateone=new DelegationChain(HelloWorld.Fun2); 9 //

第5章 基元类型、引用类型和值类型

5.1编程语言的基元类型 编译器(Compiler)直接支持的数据类型称为基元类型(primitive type). 我希望编译器根本不要提供基元类型名称,强制开发人员使用FCL(Framework类库)类型名称: 许多开发人员都困惑于到底应该使用string还是String.由于C#的string直接映射到System.String,所以两者是没有区别的.int始终映射到System.Int32,所以不管在什么操作系统上运行,代表的都是32位整数. 5.2引用类型和值类型 虽然FCL中大多数类