C#-委托delegate

目录

  • 委托的定义
  • 委托的声明
  • 委托的实例
  • 委托的注意细节
  • 泛型委托(详见《精通C#》--10.4泛型委托)
    • 1.Action<>委托
    • 3.Func<>委托
  • 附录



委托的定义

【定义】:委托是C#中函数回调机制,就是c语言中的函数指针在面向对象中的封装;简而言之就是函数指针。

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

委托和类相似,都是用户自定义的一种类型,只不过类表示的数据的集合,而委托表示的是一个或多个方法

【理解】:类比声明一个字符类型的变量“string name ”,其中string 是一个类,定义了name参数所能代表的值的种类,也就是name参数的类型。

【作用与意义】:
这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

委托可以降低类与类之间的耦合性



委托的声明

【使用方法】:
关键字 delegate
委托和所引用的方法必须保持一致:
1、参数个数、类型、顺序必须完全一致。
2、返回值必须一致。



委托的实例

    //声明一个委托指向一个函数,注意声明在同一个命名空间
    public delegate void DelSayhi(string name);

    class Program
    {
        static void Main(string[] args)
        {
            //---------------------------------------------------------------------法1
            //DelSayhi del=new DelSayhi (SayhiChinese );
            //☆注意函数名直接赋值给委托,不需要在函数名之后加括号
            //Sayhi("志铭", del);
            //委托就是为把一个函数当参数,但这样不明显


            //---------------------------------------------------------------------法2
            //可以直接把一个函数给委托
            //DelSayhi del = SayhiChinese;
            //☆注意函数名直接赋值给委托,不需要在函数名之后加括号
            //Sayhi("志铭", del);


            //---------------------------------------------------------------------法3
            //既然可以法2 ,那干脆直接如下,这样你就可以发现函数作为了参数
            //Sayhi ("志铭", SayhiChinese);

            //---------------------------------------------------------------------多播委托
            //委托可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,
            //这就是——多播委托
            //当调用这个委托的时候,将依次调用其所绑定的方法。在这个例子中,语法如下
            //DelSayhi del=new DelSayhi (SayhiChinese );
            //del += SayhiEnglish;//使用+=给此委托变量再绑定一个方法
            //Sayhi("志铭", del);


            //---------------------------------------------------------------------取消绑定
            //既然给委托可以绑定一个方法,
            //那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”:
            //DelSayhi del = new DelSayhi(SayhiChinese);
            //del += SayhiEnglish;//使用+=给此委托变量再绑定一个方法
            //Sayhi("志铭", del);

            //del -= SayhiChinese;//使用-=给此委托变量取消绑定一个方法
            //Sayhi("志铭", del);


            //不使用SayHi函数,在新建了了委托对象后直接使用委托作函数
            //注:当然我们知道可以在这里直接使用SayhiChinese和SayHiEnglish俩个函数,我们在这里就是举例子
            DelSayhi del = new DelSayhi(SayhiChinese);
            if (null != del)//注意调用委托的时候一定要先判断委托是否为空,为空时会抛异常
            {
                del("志铭");//其实是del.Invoke("志铭")的简写
            }

            Console.ReadKey();

        }

       
        //Sayhi这个函数就是为了把下面两个函数SayhiChinese和SayhiEnglish统一起来
        //我想在这个函数中调用这两个函数,也就是有一个函数作为参数,但具体哪一个不确定
        //所以我定义了一个委托DelSayhi指向这两个函数
        
        public static void Sayhi(string name, DelSayhi del)
        {
            del(name);
        }


        public static void SayhiChinese(string name)
        {
            Console.WriteLine("你好" + name);
        }

        public static void SayhiEnglish(string name)
        {
            Console.WriteLine("Hello" + name);
        }
    }



委托的注意细节

  1. 带有返回值的委托

如果委托有返回值并且在调用列表中有一个以上的方法(即多播委托),会发生下面的情况。

  • 调用列表中最后一个方法返回的值就是委托调用返回的值。
  • 调用列表中所有其他方法的返回值都会被忽略。

例如

delegate int mypel();//声明有返回值的方法

class MyClass
{
    int IntValue 5;
    public int Add2(){ Intvalue +=2;return IntValue;}
    public int Add3(){ IntValue +=3;return IntValue;}
}

class Program
{
    static void Main()
    {
    MyClass mc=new MyClass();

    MyDel mDel=mc.Add2;//创建并初始化委托
    
    mDel +=mc.Add3//增加方法
    
    mDel +=mc.Add2//增加方法
    Console.Writeline("value:{0}",mDe1());调用委托并使用返回值
    }

}

结果:value:12;



泛型委托(详见《精通C#》--10.4泛型委托)

.net中内置类两个委托类型Action<>和Func<>,用法和自己定义的委托一样,只是不需要我们自己声明。

建议使用委托的时候就先考虑这两种委托



1.Action<>委托

Action<>类型的委托指向--最多16个参数并返回值为void的方法


class Program
    {
        static void Main(string[] args)
        {
            Action del=SayhiChinese;//定义一个Action委托,指向的方法返回值为void,有一个string类的参数。
            
            //你想想,你之前使用委托是不是要要自己声明一个委托类型了
            //这里就相当于.net已经帮我们 delegate void Action(T p)
            

            if (null != del)
            {
                del("志铭");
            }

            Console.ReadKey();

        }

        public static void SayhiChinese(string name)
        {
            Console.WriteLine("你好" + name);
        }

        public static void SayhiEnglish(string name)
        {
            Console.WriteLine("Hello" + name);
        }
    }



3.Func<>委托

Func<>类型的委托指向--最多16个参数且有返回值的方法

有一点要注意的就是,类型列表的顺序:Func<>最后的一个类型参数是返回值的类型

show your code:

class Program
    {
        static void Main(string[] args)
        {
            Func del=SumToString;
            //注意类型参数列表中的类型顺序,最后一个string 是函数返回值的类型
            //这里就相当于.net已经给我们  delegate RT Func(T1 x,T2 y)
            
            Console.WriteLine(del(1,2));
        }

        public static string SumToString(int x,int y)
        {
            return (x+y).ToString();
        }

       
    }



附录

  1. 在代码结构的设计上使用委托可以降低类与类之间的耦合性。

    有两个类AClass和BClass,现在当某个条件得到满足的时候,AClass中的方法AFunc调用BClass中的方法BFunc()。

    代码如下:


public class Program
{
    AClass AObj = new AClass();
    void Main()
    {
        AObj.AFunc();
    }
}

public class AClass
{
    BClass BObj=new BClass();

      public void AFunc()
     {
         //当某个条件满足时
         if(true)
         {
            BObj.BFunc();
         }
     }
}

public class BClass
{
    public void BFunc()
     {

     }
}

这样的写法使得A类和B类之间的关系为强耦合的关系,B的变化会在很大的几率上影响到A,我们将这样的关系称之为不稳定的关系,这是面向对象编程设计所不提倡的,那么如何将不稳定的关系变为稳定的关系呢?方法有多种,委托的应用就是其中一种。

代码如下:

//声明一个委托类型,它能接受的函数类型是没有返回也没有参数

public delegate void MyDelegate();

public class AClass
{
    //定义一个委托类型的变量 ,变量名字为 mydelagate
    public MyDelegate mydelagate = null;

    public void AFunc()
     {
        //当某个条件满足时
        if(true)
        {
            if(mydelagate != null)
            {
               mydelagate();
            }
         }
     }
}

public class BClass
{
    public void BFunc()
     {

     }
}

public class Pragrom
{
    AClass AObj = new AClass();
    BClass BObj = new BClass();
    void Main()
    {
        AObj.mydelagate = BObj.BFunc();
        AObj.AFunc();
    }
}

可以看到,只需要将B类中的方法通过公开的委托注册到A类去执行,这样就避免了A类和B类之间的相互引用,提高了类关系之间的稳定性。

你可能感兴趣的:(C#-委托delegate)