zoukankan      html  css  js  c++  java
  • C#委托和事件(2)

    面试例题2:编写关于多点委托应用的实例。

    考点:了解多点委托的创建方法,选择多点委托所引用方法返回值。

    出现频率:★★

    解答

    本题创建多点委托,实现用户输入内容后,4个方法逐一被引用,达到"一触即发"的效果。解决方案是建立一个委托对象,根据不同方法的引用创建多个委托类型对象,并累加至同一个对象中。在目录下新建一个程序文件,并命名为MultiDel.cs,编写代码如代码7.2所示。

    代码7.2  C#的多点委托:MultiDel.cs

    using System;
    namespace NET.CHP6
    {
    class MultiDel
    {
    //定义1个MyHandler委托类型,其签名接收1个string类型参数,返回类型为void
    public delegate void MyHandler(string message);
    static void Main(string[] args)
    {
    //声明MyHandler类型的mh变量
    MyHandler mh;
    //创建MyHandler对象,指向MethodA方法
    mh = new MyHandler(MethodA);
    //再次创建MyHandler对象,指向MethodB方法
    mh += new MyHandler(MethodB);
    //第3次创建MyHandler对象,指向MethodC方法
    mh += new MyHandler(MethodC);
    //第4次创建MyHandler对象,指向MethodC方法
    mh += new MyHandler(OutSide.MethodD);
    Console.WriteLine("请输入参数:");
    //接收用户输入值并赋值给InputValue变量
    string InputValue = Console.ReadLine();
    mh(InputValue);
    }
    //定义3个静态方法,符合MyHandler委托类型的签名
    static void MethodA(string content)
    {
    Console.WriteLine("\n(1)这是第1个方法执行
    结果,你输入的内容大写形式为:" + content.ToUpperInvariant());
    }
    static void MethodB(string content)
    {
    Console.WriteLine("\n(2)这是第2个方法执行
    结果\n你输入的内容小写形式为:" + content.ToLowerInvariant());
    }
    static void MethodC(string content)
    {
    Console.WriteLine("\n(3)这是第3个方法执行结
    果\n你输入的内容为" + content.GetType()+"类型数据");
    }       
    }
    //定义外部类,其内含静态方法MethodD符合MyHandler委托类型签名
    class OutSide
    {
    internal static void MethodD(string content)
    {
    Console.WriteLine("\n(4)这是第4个方法(外部
    类的静态方法)执行结果\n你输入的内容有" + content.Length + "个字符");
    }
    }
    }
    多点委托也称为多路广播,可以保证指定委托类型的对象能够触发多个方法的执行,简化程序中多个方法的联合使用,并且便于事件驱动编程的编写。在命令行下编译MultiDel.cs,执行MultiDel程序,其结果如图7.4所示。
     
    (点击查看大图)图7.4  C#的多点委托执行结果

    注意:多点委托的委托类型必须保证相同,另外,多点委托所引用的多个方法都有返回值的情况下,只有最后被调用的方法才有返回值。

    解析

    在上节的学习中,了解到委托的基本使用方法。而一个委托类型对象只能指向一个方法,用多点委托可以链式地引用多个方法。简单地说,多点委托可将多个委托对象组合起来使用,类似于糖葫芦串在一起的方式,并且多个方法的引用有先后顺序。多个委托组合有以下两种方法

    (1)声明多个委托类型对象引用变量,分别指向对应的方法,将委托类型对象引用变量用加号加入到委托类型对象引用变量中,如以下代码所示:

    委托类型 对象名称 = new 委托类型(方法引用名称);
    委托类型 对象名称2 = new 委托类型(方法引用名称2);
    对象名称 = 对象名称 +对象名称2;

    注意:加入顺序决定了方法引用的顺序。

    (2)创建多个对象,使用"+="运算符累加到同一个委托类型对象的引用变量中,如以下代码所示:

    委托类型 对象名称 = new 委托类型(方法引用名称);
    对象名称+ = new 委托类型(方法引用名称2);
    相应地,如果需要将所指方法从方法调用列表中删除,可以使用"-="运算符,如以下代码所示:
    委托类型 a = new 委托类型(方法引用名称1);
    委托类型 b= new 委托类型(方法引用名称2);
    a+ = b;
    a- = b;

    以上代码首先将方法引用名称1和方法引用名称2加入a对象的方法调用列表,然后将方法引用名称2的委托删除。

    说明:"+="运算符和"-="运算符被重载,编译时这2个运算符分别转换为调用Delegate类的Combine()静态方法和Remove()静态方法。

    面试例题3:编写简单的事件机制实例。

    考点:理解C#的事件机制,事件的创建方法和事件与委托的联系。

    出现频率:★★★★

    解答

    本题要求接收用户输入,以触发事件形式执行订阅该事件的方法。解决方法是创建一个类,在类中添加一个公开属性Text,属性Text被赋值时,将触发事件Get。此时事件Get的事件处理方法被执行。在目录下新建一个程序文件,并命名为EventDel.cs,编写代码如代码7.3所示。

    代码7.3  C#的事件机制:EventDel.cs

    using System;
    class EventDel
    {
    static void Main(string[] args)
    {
    //创建Name类的对象myname
    Name myname = new Name();
    //向myname对象的Get事件注册事件处理方法myname_get
    myname.Get += new Name.myEventHandler(myname_get);
    Console.Write("\n请输入你的名字:");
    //接收用户的输入值并赋值给input变量
    string input = Console.ReadLine();
    //将input变量赋值给myname对象的Text属性
    myname.Text = input;
    }
    //定义用于订阅事件的myname_get方法
    //自定义事件信息类为Name类的嵌套类
    static void myname_get(object sender, Name.NameEventArgs e)
    {
    //输出事件信息和事件发布者的属性
    Console.WriteLine("\n\t=========事件处理方法=========");
    Console.WriteLine("事件信息:{0}", e.ToString());
    Console.WriteLine("事件发布者是:{0}", sender.ToString());
    Console.WriteLine("你输入的名字是:{0}", ((Name)sender).Text);
    }   
    }
    class Name
    {
    private string _name;
    //定义myEventHandler委托类型
    public delegate void myEventHandler(object sender, NameEventArgs e);
    //定义Get事件
    public event myEventHandler Get;
    //定义可读写的Text属性
    internal string Text
    {
    get
    {
    return this._name;
    }
    set
    {
    this._name = value;
    //调用OnGet方法,并传递NameEventArgs类对象
    this.OnGet(new NameEventArgs("Text属性被更改了"));
    }
    }
    //定义OnGet方法,接收1个EventArgs类型的参数
    void OnGet(NameEventArgs e)
    {
    //触发Get事件,传递2个参数
    this.Get(this, e);
    }
    //重写ToString()方法
    public override string ToString()
    {
    return "Name类的对象";
    }
    //自定义事件信息类,继承于EventArgs类
    public class NameEventArgs : EventArgs
    {
    string _args;
    //重载构造函数,用于将参数值赋值给_args字段
    public NameEventArgs(string s)
    {
    _args = s;
    }
    //重写ToString()方法,返回_args字段
    public override string ToString()
    {
    return _args;
    }
    }
    }
    以上程序功能非常简单,即显示用户输入,事件触发后调用事件处理方法。在命令行下编译EventDel.cs,执行EventDel程序,程序提示"请输入你的名字",输入"叶青",运行结果如图7.5所示。
     
    (点击查看大图)图7.5  C#的事件机制


    当用户输入值后,myname对象的Text属性被赋值,程序执行OnGet()方法,并传递自定义事件类NameEventArgs的对象。而OnGet()方法将触发Get事件,并传递对象自身以及NameEventArgs类的对象作为参数。订阅了Get事件的myname_get()方法被通知,主程序立即调用myname_get()方法,在方法中输出自定义事件类的字符串,以及事件发布者的字符串形式和属性值。

    说明:必须理解事件和委托的联系,才能掌握事件机制的本质。

    解析

    大部分应用程序包括JavaScript、ActionScript等都有异步事件处理机制,而在C#中是由多点委托和事件来实现这种机制的。

    这种设计模式可以称为"发布者/订阅者模式",发布者发布事件,多个类订阅这个事件(类必须包含一个相应的事件处理方法)。当该事件被触发时,系统通知每个订阅者事件发生。触发事件所调用的事件处理方法是由委托来实现。在这种情况下,必须注意以下几点。

    (1)委托类型的签名必须有两个参数,分别是触发事件的对象和事件信息。

    (2)事件信息必须是由EventArgs类派生。

    这样在写触发事件的对象类时不必知道事件信息对象类。事件信息对象类可以在运行时订阅或解除订阅特定的事件。简单地说,事件就是当对象或类(发布者)状态发生改变时,对象或类发出信息通知订阅者,发布者也被称为"事件源"。

    说明:在其他语言的事件机制中也有类似的模式,如Java采用接口,在运行时使用多态的方式实现对事件接收者响应函数的调用。

    编写简单的事件机制需要先定义委托类型,然后通过委托类型定义事件,最后事件处理方法订阅事件。假设定义了名为MyDel委托类型,事件名称为onclick,定义部分如以下代码所示:

    public delegate 返回类型 MyDel(object sender, EventArgs e);
    public event MyDel onclick
    MyDel 委托对象名称 += new MyDel(事件处理方法);
    //事件处理方法订阅onclick事件
    onclick += 委托对象名称;
    //事件处理方法取消订阅onclick事件
    onclick -= 委托对象名称;
    从以上代码可以看出,事件实质上是一种特殊的委托,通过多点委托的方法被多个方法订阅。当事件触发时,相应的事件处理方法将会被引用。

  • 相关阅读:
    react-redux简单使用
    jQuery——Js与jQuery的相互转换
    移除HTML5 input在type="number"时的上下小箭头
    echarts 5.0 地图
    Vue echarts 设置初始化默认高亮
    echarts 渐变色
    隐藏滚动条css
    echarts 柱状图--圆角
    echarts 气泡图--option
    Vue 圆柱体组件
  • 原文地址:https://www.cnblogs.com/jordan2009/p/1632137.html
Copyright © 2011-2022 走看看