委托

2018-11-13  本文已影响1人  ottox

委托的概念:

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。事件是一种特殊的委托。
本质是持有一个或多个方法的对象;委托和典型的对象不同,执行委托实际上是执行它所“持有”的方法。如果从C++的角度来理解委托,可以将其理解为一个类型安全的、面向对象的函数指针。


image.png

如何使用委托

①声明委托类型(delegate关键字)

②使用该委托类型声明一个委托变量

③为委托类型增加方法

④调用委托执行方法


image.png

声明委托

delegate <函数返回类型> <委托名> (<函数参数>)

image.png

a、委托类型的声明看上去与方法的声明很类似,有返回类型和签名。返回类型和签名指定了委托接受的方法的形式
b、委托类型与方法声明的不同之处:
▲ 委托是以关键字delegate开头的
▲ 委托没有方法主体

例子:public delegate void MyDelegate(int number);//定义了一个委托MyDelegate,它可以注册返回void类型且有一个int作为参数的函数

委托的实例化

委托实例化的原型是
<委托类型> <实例化名>=new <委托类型>(<注册函数>)
例子:MyDelegate _MyDelegate=new MyDelegate(CheckMod);//用函数CheckMod实例化上面的MyDelegate 委托为_MyDelegate
简写:MyDelegate _MyDelegate=CheckMod;

<委托类型> <实例化名>=delegate(<函数参数>){函数体};

class Program
    {
        //声明委托
        delegate int MyDelegate(int x, int y);

        static void Main(string[] args)
        {
            //实例化委托
            //1、使用new关键字
            MyDelegate _myDelegate = new MyDelegate(GetSum);
            //  MyDelegate _myDelegate = GetSum;

            //2、使用匿名方法
            MyDelegate myDelegate = delegate(int x, int y)
            {
                return x + y;
            };

            //3、使用Lambda表达式
            MyDelegate myDelegateLambda = (int x, int y) => { return x + y; };
        }

        static int GetSum(int x, int y)
        {
            return x + y;
        }
    }

泛型委托

泛型委托原型:
delegate <T1> <委托名><T1,T2,T3...> (T1 t1,T2 t2,T3 t3...)
例如:delegate T2 DelegateDemo<T1,T2>(T1 t);//定义有两个泛型(T1,T2)的委托,T2作为委托函数返回类型,T1作为委托函数参数类型

static boo Check(int i)
{
     if(i%2==0)

     {

          return true; 

    }

     return false;
}

static void Main(string[] args)
{
      DelegateDemo<int, bool> _delegate =Check;//将泛型委托委托<T1,T2>实例化为<int,bool>,即表示有一个int类型参数且返回类型是bool的函数.
      Console.WriteLine(_delegate(9));//false
}

C#内置泛型委托

namespace DelegateDemo
{
    class Program
    {
        //声明委托
        delegate int MyDelegate(int x, int y);

        static void Main(string[] args)
        {
            //1、Action<T>只能委托必须是无返回值的方法
            Action<string> _action = new Action<string>(SayHello);
            _action("Hello World");

            //2、Fun<TResult>只是委托必须有返回值的方法
            Func<int, bool> _func = new Func<int, bool>(Check);
            _func(5);

            //3、Predicate:此委托返回一个bool值,该委托通常引用一个"判断条件函数"。
            //需要指出的是,判断条件一般为“外部的硬性条件”,比如“大于50”,而不是由数据自身指定,如“查找数组中最大的元素就不适合”。
            Predicate<int> _predicate = new Predicate<int>(Check);
            //使用Lambda表达式
            Predicate<int> predicate = p => p % 2 == 0;
            _predicate(26);
        }

        static void SayHello(string strMsg)
        {
            Console.WriteLine(strMsg);
        }

        //返回值为bool值
        static bool Check(int i)
        {
            if (i % 2 == 0)
            {
                return true;
            }
            return false;
        }       
    }
}

多播委托

实例化委托时必须将一个匹配函数注册到委托上来实例化一个委托对象,但是一个实例化委托不仅可以注册一个函数还可以注册多个函数,注册多个函数后,在执行委托的时候会根据注册函数的注册先后顺序依次执行每一个注册函数。

函数注册委托的原型:
<委托类型> <实例化名>+=new <委托类型>(<注册函数>)
例如:MyDelegate _myDelegate+=new MyDelegate(CheckMod);//将函数CheckMod注册到委托实例_checkDelegate上
在.net 2.0开始可以直接将匹配的函数注册到实例化委托:
<委托类型> <实例化名>+=<注册函数>
例如:MyDelegate _myDelegate+=CheckMod;//将函数CheckMod注册到委托实例_myDelegate上

注意:委托必须先实例化以后,才能使用+=注册其他方法。如果对注册了函数的委托实例从新使用=号赋值,相当于是重新实例化了委托,之前在上面注册的函数和委托实例之间也不再产生任何关系。

有+=注册函数到委托,也有-=解除注册

例如:MyDelegate _myDelegate-=CheckMod;

如果在委托注册了多个函数后,如果委托有返回值,那么调用委托时,返回的将是最后一个注册函数的返回值。

namespace DelegateDemo
{
  class Program
  {
      //声明委托
      delegate int MyDelegate(int x, int y);

      static void Main(string[] args)
      {
          MyDelegate _myDelegate = new MyDelegate(fun1);
          _myDelegate += fun2;
          Console.WriteLine(_myDelegate(10,23));

          Console.ReadKey();//输出10,返回最后一个注册函数的返回值
      }

      static int fun1(int x, int y)
      {
          return x + y;
      }

      static int fun2(int x, int y)
      {
          return x;
      }      
  }
}

委托实例

①简单带参数委托DEMO

delegate void MyDel(int value); //声明委托类型

    class Program
    {
        void PrintLow(int value)
        {
            Console.WriteLine("{0} - LowValue", value);
        }

        void PrintHigh(int value)
        {
            Console.WriteLine("{0} - HighValue", value);
        }

        static void Main(string[] args)
        {
            Program program = new Program();

            MyDel myDel; //声明委托类型

            //获取0~99之间的一个随机数
            Random random = new Random();
            int randomValue = random.Next(99);

            //创建一个包含具体方法的委托对象并将其赋值给myDel变量
            myDel = randomValue < 50 ?
                new MyDel(program.PrintLow) : new MyDel(program.PrintHigh);

            //执行委托
            myDel(randomValue);

            Console.ReadKey();
        }
    }

②简单无参数多方法列表委托DEMO

delegate void PrintFunction();

class Test
{
   public void Print1()
   {
      Console.WriteLine( "Print1 -- instance" );
   }

   public static void Print2()
   {
      Console.WriteLine( "Print2 -- static" );
   }
}

class Program
{
   static void Main()
   {
      Test t = new Test();                 
      PrintFunction pf;                        
      pf = t.Print1; 

      pf += Test.Print2;
      pf += t.Print1;
      pf += Test.Print2;

      if ( pf != null )                         
      {
          pf();    
       }                          
      else
       {  
           Console.WriteLine( "Delegate is empty" ); 
       }
   }
}

③带返回值的委托DEMO

delegate int MyDel(); 

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}", mDel() );
   }
}
上一篇下一篇

猜你喜欢

热点阅读