• 学前教育
  • 小学学习
  • 初中学习
  • 高中学习
  • 语文学习
  • 数学学习
  • 英语学习
  • 作文范文
  • 文科资料
  • 理科资料
  • 文档大全
  • 当前位置: 雅意学习网 > 高中学习 > 正文

    乐高ev3机器人编程自学 [代理及其编程方法]

    时间:2020-07-14 07:24:20 来源:雅意学习网 本文已影响 雅意学习网手机站

      摘要:在C#语言中,可以用代理(Delegate)来动态地调用不同的函数。本文针对代理的基本概念、用代理编程的基本结构及多重代理进行讨论,并通过实例程序进行必要的说明。
      关键词:函数指针;代理;多重代理
      中图分类号:TP312 文献标识码:A
      
      1 代理的基本概念
      
      在C/C++中,函数调用有两种方式:一种是通过函数名直接调用;另一种是利用指向函数的指针进行调用。指向函数的指针又简称为函数指针。采用函数指针调用函数,可以达到通过一个函数指针调用多个功能不同、但函数的参数及返值类型一致的函数。
      1.1 函数指针
      在C/C++中,函数名表示函数在存储区域的首地址,即是函数执行的入口地址。在程序中调用一个函数时,程序控制流程将转移到以该函数名为入口地址的地方执行该函数。
      函数指针定义的一般形式是:
      数据类型(*函数指针名)(参数表);
      其中数据类型是函数指针所指向的函数所具有的返值类型,参数表是被调函数所具有的参数表。
      一般来讲,函数指针得到某个函数名的赋值,程序将调用该函数;在函数指针作为函数的形参时,需要进行取内容的运算才能调用对应的函数。例如:
      exe(int x,int y,int (*func)())
      { return((*func)(x,y));}
      在上述exe函数中,int (*func)()是函数指针,而“((*func)(x,y));”程序将转向由func所指向的函数去执行,其参数是x和y。
      使用函数指针编程方法一般为:定义相应的函数;定义函数指针;通过某种操作使函数指针得到函数名的赋值;最后连同参数调用相应的函数。
      1.2 代理及其相关概念
      在C#中,代理(delegate)的作用类似于C/C++中的函数指针。C#中的方法类似于C/C++中的函数,其方法名也是一个物理地址。方法的入口地址可以赋给“代理”,进而通过“代理”调用该方法;且同一个代理可以调用多个不同的方法。使用代理可以在程序的运行期间动态地调用所需的函数。
      代理定义的一般格式为:
      [访问控制修饰符] delegate返值类型 代理名([形式参数表]);
      其中:访问控制修饰符可以是new、public、protected、internal和private。new修饰符表明当前定义的代理将隐藏继承来的同名代理;public修饰符表明所有对象都可以访问该定义的代理;protected修饰符表明定义该代理的类及其子类可以访问该代理;internal修饰符只有代理所属的工程项目的成员可以访问该代理;private修饰符表明只有定义该代理的类才能访问该代理。
      delegate是定义代理的关键字。代理名是符合C#的任意合法的标识符。返值类型是指该代理所调用方法的返值类型。形式参数表用于指出代理所调用方法的参数表。
      例如,在一个类中定义一个代理MyDel_ egate:
      classMyClass
      { ……
      public delegate void MyDelegate(string s);
      ……
      }
      在上述代理定义中的void表示该代理指向的方法不返回任何值,string s表示该代理所指向的方法将接受一个字符串参数。
      在C#中,定义一个代理MyDelegate, C#编译器将根据代理的定义语句自动生成一个从System.MulticastDelegate类派生的子类MyDelegate。
      
      2 使用代理的编程结构
      
      代理类似于C/C++的指向函数的指针,但是代理的使用范围比函数指针更加广泛。在C中,函数只有外部和静态函数两种,它们都属于静态函数的范畴;在C ++中,函数指针只能引用静态方法,而代理不仅可以引用静态方法,还可以引用对象的实例方法。
      2.1 使用代理的编程结构
      使用代理编程和在C/C++中使用函数指针类似,一般有:定义将要由代理调用的方法;声明一个代理;定义delegate处理的函数;创建实例并调用相应方法。
      (1)定义拟调用的方法
      该类方法的函数返值类型,函数形参的参数类型、个数及参数的顺序,决定了定义delegate类型代理时的相应参数。例如:
      public static string FunctionA
      (string name) {……}
      public static string FunctionB
      (string name) {……}
      (2)声明一个代理
      该代理的返值类型,参数的类型、个数及参数的顺序都必须与拟调用的方法的返值类型,形参类型、个数及参数的顺序完全相同。例如:
      public delegate string MyDelegate (stringname);
      (3)定义delegate类型处理的函数
      定义delegate类型处理的函数,并在此函数中通过delegate类型调用定义的方法。
      public static void MethodA(MyDelegateMe)
      {Console.WriteLine(Me(“张三”));}
      (4)创建实例并调用方法
      由于声明一个delegate类型的代理在编译时将被转换成一个MulticastDelegate类的派生类,因此在使用代理时,必须要先创建该类的实例,并把它与一个方法关联。
      MyDelegate a=new MyDelegate (FunctionA)
      本语句的含义是:a引用指向方法FunctionA的程序代码段。
      通过delegate处理函数调用相应的方法。MethodA(a);
      2.2 使用代理编程实例
      using System;
      namespace ConDelegatejl
      { public class Test
      { //第一步:声明委托
       public static string FunctionA(string name)
       {return“A say Hello to”+name;}
       public static string FunctionB(string name)
       {return “B say Hello to ”+name;}
       //第二步:定义被调用的方法
      public delegate string MyDele gate(string name);
      //第三步:定义delegate类型处理函数
      public static void MethodA (MyDelegate Me)
      {Console.WriteLine(Me(“张三”));}
       public static void Main()
      { //第四步:创建实例,
      //准备调用的方法名
      MyDelegate a = new MyDelegate (FunctionA);
      MyDelegate b = new MyDelegate (FunctionB);
      MethodA(a); MethodA(b); Console.Read();
      }
      }
      上述程序的运行结果如下图所示。
      
      
      3 多重代理及其实现
      
      在C#语言中,每一个代理实例(对象)都含有一个调用链表,该链表可以包含多个该代理要调用的方法,此种机制用于一个代理实例可以调用多个方法,也就是多重代理(多播)。多播要创建方法链表,当调用代理时,所有被链接的方法都会被自动地调用。
      3.1 Delegate类和MulticastDelegate类
      所有的代理类都是由MulticastDele gate类派生的,而MulticastDelegate类又是由Delegate类派生的,它们都位于System命名空间下。
      Delegate类有两个公用的只读属性:
      Method属性:本属性用于获得代理实例要调用的静态方法。可以用如下代码获得代理对象所调用的方法名。
      stringMethodName=代理名.Method;
      Target属性:该属性可以获得代理对象所在的类;如果代理调用的是静态方法,其返值为null,否则将返回代理实例所调用方法所在类名。如下代码可以获得代理调用方法所在类的名称。
      stringObjType=代理名.Target;
      如果代理调用多个方法,则该属性将返回调用列表中最后一个实例方法所在的类名。
      3.2 MulticastDelegate类实现多重代理的机制
      从MulticastDelegate类派生的用户代理实例中含有一个调用链表,该链表将由多个代理实例组成,其中每个代理实例都封装一个相应的方法,也就是一个代理实例可以同时调用多个方法。代理实例通过_prev私有指针来连接多个代理构成的链表,私有指针_target和_methodPtr用于指向代理实例调用的实例和方法。
      每创建一个新的代理实例时,指针_prev将被设置为null,表示链表中没有其它的代理实例。而当用户使用Combine方法(或+=运算符)把另一个代理实例合并到该调用链表中时,则将先创建一个含有_target和_methodPtr值的新实例,然后把该实例的_prev设置为调用链表的头实例,即从调用链表的头插入新的实例。可以使用Remove方法(或-=运算符)从一个调用链表中删除一个代理实例。
      3.3 多重代理编程的实现
      多重代理(或多播)具有创建方法链表的能力,当调用代理时,所有被链接的方法都会被自动调用,也就是多播可以在一次代理调用中调用方法链表上的所有方法。创建多播调用链表的方法是:先实例化一个代理,然后使用“+=”运算符把方法添加到调用链表中;也可以使用“-=”运算符从调用链表中删除一个方法。
      下面程序说明了多重代理编程的实现方法。
      using System;
      using System.Collections.Generic;
      using System.Text;namespace ConDelegatej2
      {
       delegate void StringDelegate(
      ref string str);//定义一个代理
       class stringops//字符串操作类
       { //定义三个字符串操作方法
       static void ReplaceSpaces(ref string s)
      { Console.WriteLine("用连字符替换
      空格操作:");
      s = s.Replace(" ", "_");
      }
      static void RemoveSpaces(ref string s)
      { string temp = "";int i;
      Console.WriteLine("删除空格操作:");
      for(i=0; i=0;j--)
      temp += s[j];
       s = temp;
       }
      static void Main(string[]args)
      {//创建一个代理
      StringDelegate strdelegate;
      StringDelegate replacesp=new
      StringDelegate(ReplaceSpaces);
      StringDelegate removes =new
       StringDelegate(RemoveSpaces);
      StringDelegate reversestr=new StringDelegate(Reverse);
      string str = "Iam astudent.";
      //代理指向一个函数
      strdelegate =replacesp;
      strdelegate += reversestr;//多播关联
      strdelegate(ref str );//调用多播
      Console.WriteLine("操作字符串的结果为:"+str);
      Console.WriteLine();
      strdelegate-=replacesp;//去除replacesp
      strdelegate += RemoveSpaces;
      str ="你是一个计算机教师.";
      strdelegate (refstr);
      Console.WriteLine("字符串操作结果是:"+str);
       Console.WriteLine ();Console.Read();
      }
       }
      }
      上述程序的运行结果如下所示。
      
      
      4 结束语
      
      代理是C#语言提供动态调用函数的一种方法;多重代理解决了用一个代理一次调用多个方法的技术。不过代理的多播有一个限制:方法链表中的方法必须具有相同的参数,而且这些方法的返回值类型要是void类型。
      代理也为用户程序利用属性驱动事件程序的编程提供了有力的方法。
      
       参考文献
      [1]唐大仕编著. C#程序设计教程[M]. 北京: 清华大学出版社; 北方交通大学出版社, 2003.
      [2]邵鹏鸣编著. Visual C#程序设计基础教程[M]. 北京: 清华大学出版社, 2005.

    推荐访问:编程 代理 方法 代理及其编程方法 编程通讯线代理 可编程触摸屏代理

    • 文档大全
    • 故事大全
    • 优美句子
    • 范文
    • 美文
    • 散文
    • 小说文章