9159金沙游艺场

图片 4
win10连接外接鼠标怎么禁用触摸板

MySQL的锁

c# 委托 delegate

本篇文章主要介绍委托的应用。

委托是一种存储函数引用的类型,在事件和事件的处理时有重要的用途

委托是大家最常见的语法了,但会用与精通之间的差别是巨大的。

通俗的说,委托是一个可以引用方法的类型,当创建一个委托,也就创建一个引用方法的变量,进而就可以调用那个方法,即委托可以调用它所指的方法。

一个程序员如果不能精通委托,那么,他永远无法成为高级程序员。

 

所以,让我们把委托刻到血液里吧。

  1. 使用委托

这样,你才能称为[Developer]。

委托的使用需要以下步骤:

委托的定义

定义委托

什么是委托?

delegate double ParocessDelegate(double param1,double param2);

委托实际上是一种类型,是一种引用类型。

委托的定义非常类似于函数,但不带函数体,且要使用delegate关键字。委托定义需要指明委托名称以及一个返回类型和一个参数列表

微软用delegate关键字来声明委托,delegate与int,string,double等关键字一样。都是声明用的。

 

下面先看下声明代码,这里声明了两个委托。

声明委托类型的变量

public delegate void TestDelegate(string message);
public delegate int TestDelegate(MyType m, long num);
ProcessDelegate process;

delegate既然是关键字,和int,string一样,那么,为什么delegate后又跟了一个void或者int呢?

定义了委托后,就可以声明一个该委托类型的变量

如果他们是同等地位的关键字,为什么可以一起使用呢?

 

很简单,我们把delegate后面的 【void TestDelegate(string
message)】理解为一个变量,是不是就清晰明了了一些。

初始化委托变量

我们把delegate关键字理解为,是用来专门来定义这种复杂的变量的。而这种复杂的变量可以包含一个返回值和任意数目任意类型的传入参数。

process =new ProcessDelegate(Multiply);

有没有感觉,这个复杂的变量特别像一个函数的定义。

初始化委托变量时要把一个函数(此处Multiply为一个函数的名称)引用赋给委托变量,此函数需要具有与委托相同的返回类型和参数列表。c#使用上述略显古怪的语法,使用new关键字创建一个新的委托,参数为
要引用所需的函数,这是委托赋值的一个独特语法,函数名称是不带括号的

没错,官方定义,委托类型的声明与方法签名相似。所以,这个复杂变量,的确,书写的方式就是与函数一样。

还可以用另一种略微简单的语法

那么,为什么这个声明方式如此怪异呢,是因为,我们用delegate定义的变量,只能用函数赋值。赋值方式如下所示:

process = Muiltiply;
public delegate void TestDelegate(string message);
public delegate long TestDelegate2(int m, long num);
public static void Excute()
{
    TestDelegate2 td = Double; 
} 
static long Double(int m, long num)
{
    return m * num;
}

 

委托的基本应用

有了引用函数的委托变量之后,我们就可以用委托变量调用Muiltiply函数;也可以把委托变量传递给其他函数

学会了赋值以后,我开始使用委托。

process (param1,param2);

委托的使用方式如下:

 

string result = td(51, 8);
Console.WriteLine(result);

示例:

这里我们会发现,委托的使用方式与函数调用一样。

namespace Delegate
{

        public delegate int Call(int num1, int num2);//第一步:定义委托类型
        class SimpleMath
        {
            // 乘法方法
            public int Multiply(int num1, int num2)
            {
                return num1 * num2;
            }

            // 除法方法
            public int Divide(int num1, int num2)
            {
                return num1 / num2;
            }
        }
    }
    class Test
    {
        static void Main(string[] args)
        {
            Call objCall;//第二步:声明委托变量
            // Math 类的对象
            SimpleMath objMath = new SimpleMath(); 
            // 第三步:初始化委托变量,将方法与委托关联起来
            objCall = new Call(objMath.Multiply);


            objCall += objMath.Divide;//向委托增加一个方法
            //objCall -=  objMath.Divide;//向委托减去一个方法

            // 调用委托实例,先执行objMath.Multiply,然后执行objMath.Divide
            int result = objCall(5, 3);
            System.Console.WriteLine("结果为 {0}", result);
            Console.ReadKey();
        }
    }

没错,它们的确是一样的。因为委托是用函数来赋值的,所以调用方式一样也并不奇怪,不是吗。

注意事项:

换一种说法,就是委托封装了一个函数。

  • 委托可以调用多个方法,即一个委托变量可以引用多个函数,称为多路广播
  • 可以使用+=和-=运算符实现方法的增加和减少
  • 无返回值的委托,引用了多少个方法就会执行多少个方法。有返回值的委托同样会执行多个引用的方法,但返回的值是最后一个方法的返回值

如果委托是封装的函数,并且它又是引用类型。那么委托第一种常规的应用就浮现出来了。

 

那就是——引用类型的函数。

 

如果函数是引用类型,那么这个函数只要没被内存回收,就可以被调用。如果是public函数或者是public
static函数,那么它能跨越的东西就更多了。

  2.  其他形式的委托

比如可以跨类调用,跨程序集调用等等。而这种用法,就是委托的基本应用。

  • 匿名委托

匿名委托的应用

匿名委托使用起来更简洁一点,不用在定义一个专用的委托函数来传递方法,也更可以更好的理解委托

匿名委托的官方介绍:在 2.0 之前的 C#
版本中,声明委托的唯一方式是使用命名方法。 C# 2.0 引入匿名方法,在 C#
3.0 及更高版本中,Lambda 表达式取代匿名方法作为编写内联代码的首选方式。

  //定义委托
    delegate string lookMe(string s);

    protected void LinkButton1_Click(object sender, EventArgs e)
    {
        //匿名委托
        lookMe lm = delegate(string name) { return "亲爱的 " + name + ",请看着我的眼睛!"; };

        //匿名委托调用
        string name1 = "jarod";
        Label1.Text = lm(name1);
    }

看不懂没关系,我们直接来学习使用。代码如下:

 

delegate string anonymousDelegate(int m, long num);
public static void Excute()
{
    anonymousDelegate ad = delegate (int m, long num) { return m.ToString() + num.ToString(); };//2.0时代的匿名委托
    anonymousDelegate ad2 = (m, num) => { return m.ToString() + num.ToString(); };//3.0以后匿名委托 
}
  • 泛型委托

如代码所示,匿名委托是Lambda表达式,不懂的同学就当它是有固定写法即可,不用讲什么道理,只要记住并应用即可。

Action<>,Func<>,Predicate<>
其实他们都是委托代理的简写形式,通过他们可以省去定义委托的步骤

匿名委托虽然减少了一点代码,但还是要求我们自己去声明委托。所有,还能再简写一点吗?

示例

答案当然是,可以的。

public static void HellowChinese(string strChinese)  
{  
    Console.WriteLine("Good morning," + strChinese);  
    Console.ReadLine();  
}  

Action<string> action = HellowChinese;  
action("Spring.");  

Action与Func

其中Action是无返回值的泛型委托,Func是有返回值的泛型委托,Predicate<>是返回bool类型的委托,他们都有多个参数的重载版本

Action与Func是微软为我们预先定义好了的,两个委托变量。其中Action是不带返回值的委托,Func是带返回值的委托。

 

可以说,Action与Func完全包含了,我们日常使用所需的,全部的,委托变量。

 

也就是说,我们可以不用再去自己手动声明委托了。

   3.  委托的各种写法

下面来看最简单的Action与Func的定义:

public delegate int DelegateProcess(int num1, int num2);

//第一种写法
DelegateProcess process= new DelegateProcess(Multiply);

//第二种写法
DelegateProcess process= Multiply;

//第三种写法  匿名委托
DelegateProcess process= delegate(int a,int b)
{
   return a*b;
}

//第四种写法 Lamdba表达式
DelegateProcess process =((int a,int b)=>{return a*b;});

//第五种写法 Action<T>和Func<T>
Action<int,int> process= ((int a,int b)=>{Console.WriteLine(a * b);});
Func<int,int,int> process= ((int a,int b)=>{return a*b;});
Action a1 = () => { };
Func<int> f1 = () => { return 1; };//必须写 return 1;

 

Action与Func是泛型委托,各支持16个入参变量。下面代码为一个入参的定义,多参数以此类推。

Action<int> a1 = (i) =>  { };
Func<string,int> f1 = (str) => {  return 1;//必须写 return 1; };

委托的线程应用

委托的线程应用是委托的第二种用法,分为线程使用委托,和委托的异步应用两种。

我们先看线程使用委托。如下代码所示,一个无入参匿名Action和一个无入参匿名Func。

Task taskAction = new Task(() => { });//无入参匿名Action
taskAction.Start(); 
Task<int> taskFunc = new Task<int>(() => { return 1; });//无入参匿名Func
taskFunc.Start();
int result= taskFunc.GetAwaiter().GetResult();//获取线程返回结果

我们能看到两种委托应用,代码都非常简洁。

下面我们再来看委托的异步应用。首先看最简单的异步调用。

相关文章

No Comments, Be The First!
近期评论
    功能
    网站地图xml地图