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

    7.1  委托和事件(1)

    委托和事件一直被视为C#的难点,.NET的面试题中经常出现这些知识点。本节通过常见的面试考题辅以典型实例剖析,对知识点深度讲解。

    面试例题1:举例说明如何使用C#中的委托?

    考点:委托的含义,委托和引用方法的联系。

    出现频率:★★★★★

    解答

    本实例通过用户选择不同格式显示输入的文字,解决办法是首先建立委托类型,其签名可以匹配多个格式化字符,然后在Main()方法中创建委托对象,通过判断用户的输入,将委托对象进行相应地初始化,从而完成不同方法的引用。在目录下新建一个程序文件,并命名为DelegateTest.cs,编写代码如代码7.1所示。

    代码7.1  简单使用C#的委托:DelegateTest.cs

    using System;
    namespace NET.CHP6
    {
    public class DelegateTest
    {
    //定义一个MyDel委托类型,其签名接收两个string类型参数,返回类型也为string
    public delegate string MyDel(string nm, string pwd);       
    static void Main(string[] args)
    {
    //声明MyDel类型的md变量
    MyDel md;
    Console.WriteLine("请输入2个参数,并用逗号分隔");
    //将用户输入值赋值给InputValue变量
    string InputValue = Console.ReadLine();
    //获取英文逗号在InputValue变量中的索引值,并赋值给Pos变量
    int Pos = InputValue.IndexOf(",");
    //将英文逗号前面部分的子字符串赋值给ValueA变量
    string ValueA = InputValue.Substring(0, Pos);
    //将英文逗号后面部分的子字符串赋值给ValueB变量
    string ValueB = InputValue.Substring(Pos + 1);
    Console.WriteLine("请输入A,B,C,D,以确定所调用方法");
    //将用户输入值转换为大写,并赋值给InputMethod方法
    string InputMethod = Console.ReadLine().ToUpper();
    //判断InputMethod变量的值
    switch (InputMethod)
    {
    case "A":
    //如果用户输入为A或a,则创建MyDel委托对象,
    其引用变量为md,指向formatA方法
    md = new MyDel(formatA);
    break;
    case "B":
    //如果用户输入为B或b,则创建MyDel委托对象,
    其引用变量为md,指向formatB方法
    md = new MyDel(formatB);
    break;
    case "C":
    //如果用户输入为C或c,则创建MyDel委托对象,
    其引用变量为md,指向Another类的formatC静态方法
    md = new MyDel(Another.formatC);
    break;
    case "D":
    //如果用户输入为D或d,则首先创建创建Another对象,引用为ano变量
    //然后创建MyDel委托对象,其引用变量为md,指向ano对象的formatD方法
    Another ano = new Another();
    md = new MyDel(ano.formatD);
    break;
    default:
    //其他情况下,创建MyDel委托对象,其引用变量为md,指向formatA方法
    md = new MyDel(formatA);
    break;
    }
    //调用md委托对象,将返回值赋值给result变量
    string result = md(ValueA, ValueB);
    Console.WriteLine("\n\t==========以下为委托方法执行结果==========");
    //输出result变量值
    Console.WriteLine(result);
    }
    //定义两个静态方法formatA和formatB,符合MyDel委托类型的签名
    static string formatA(string a, string b)
    {
    string words = "I am the first static method.
    \nMy name is " + a + "\nMy password is " + b;
    words += "\n我是第一个静态方法。\n我的名字是:
    " + a + "\n我的密码是: " + b;
    return words;
    }
    static string formatB(string a, string b)
    {
    string words = "I am the second static method
    .\nMy name is " + a + "\nMy password is " + b;
    words += "\n我是第二个静态方法。\n我的名字是:
    " + a + "\n我的密码是: " + b;
    return words;
    }
    }
    //定义外部类,其内含静态方法和实例方法符合MyDel委托类型签名
    class Another
    {
    internal static string formatC(string a, string b)
    {
    string words = "I am the third static method,
    I belong to Another class.\nMy name is " + a + "\nMy password is " + b;
    words += "\n我是第三个静态方法,我属于 Another 类。
    \n我的名字是: " + a + "\n我的密码是: " + b;
    return words;
    }
    internal string formatD(string a, string b)
    {
    string words = "\n我是1个实例方法,我所属的对象实
    例是 Another 类所构造的。\n我的名字是: " + a + "\n我的密码是: " + b;
    return words;
    }
    }
    }

    在Main()方法以外定义了1个委托类型,其名称为MyDel,其返回值为String类型,并接收2个String类型的参数。另外还声明了2个静态方法和1个类,其中Another类含有2个方法,分别为静态方法formatC()和实例方法formatD(),这2个方法都用internal修饰。

    在Main()方法中,首先声明MyDel委托类型的对象,并命名为md。通过Console.ReadLine()方法,接收用户的输入并存储到InputValue变量中,通过","将InputValue分隔为2个字符串,分别存储于ValueA和ValueB;然后接收用户的输入并存储于InputMethod变量中,通过switch语句判定用户输入是否为A、B、C、D或其他。不同的InputMethod值通过以下代码语句初始化md的引用:

    md = new MyDel(调用方法);

    最后直接输出md的方法调用。在命令行下编译DelegateTest.cs,执行DelegateTest程序,程序提示"请输入两个参数,并用逗号分隔"。输入相应的值后,程序再次提示"请输入A,B,C,D,以确定所调用方法",输入"abcd",即4个选择以外的字母,程序运行结果如图7.1所示。

     
    (点击查看大图)图7.1  委托执行结果

    由上可知,程序中的switch分支语句执行了default条件下的代码,即调用第1个静态方法。再次运行DelegateTest程序,程序提示调用方法时,输入"d",运行结果如图7.2所示。

    如果首先输入"YeQing,password"字符串,然后输入"d",程序返回D字母对应的结果。由结果可知,委托类型对象md引用了Anothoer类的实例方法formatD()。

     
    (点击查看大图)图7.2  委托执行结果

    解析

    很多C#书籍介绍过,C#对C++的借鉴过程中去掉了指针部分,但是在学习到C#委托类型的知识点时,很多C++的程序员会想起指针。不过C#中的委托并不完全等同于指针,相对于C++中的指针,委托是面向对象的、类型安全的类型,在编程中使用更加方便、可靠。

    说明:CLR能够保证委托指向一个有效的方法,而不会指向无效地址或者越界地址。

    可将委托看作一种新的对象类型,委托主要用于.NET Framework中的事件处理程序和回调函数。委托类型可定义一个签名,并且它只能持有与它的签名相匹配的方法引用。所有委托类型对象都有方法调用列表,它是在调用委托对象时所执行方法的一个链接列表。方法调用列表所链接的方法可以是静态方法,也可以是实例方法。对于实例方法,列表中所对应的是一个实例方法和其所属实例,而对于静态方法,列表中只对应一个方法。

    说明:列表中的方法即为与委托类型定义签名相匹配的方法。

    当委托类型匹配方法的返回类型和参数列表时,这个委托类型即和此方法兼容。另外,方法的名称等特性不需要和委托类型名称匹配。用delegate 关键字可以定义一个委托,通知编译器这是一个委托类型。委托类型声明的形式类似,没有函数体的函数,但是有相应的返回值和参数列表,其格式如以下代码所示:

    public delegate 返回类型 委托名称(参数类型1 参数1,参数类型2 参数2,... );

    通过委托定义中的返回值类型和参数列表即可匹配其他方法,而委托名称是这种委托类型的名称。delegate关键字定义时,临时定义了一个派生于System.MulticastDelegate类的密封类,这个类与其基类System.Delegate均同为委托提供必要的基础成员。在使用委托时声明该委托类型的对象,然后将这个对象初始化为该委托对象签名匹配的方法引用。其结果是该委托对象调用了相应的方法,这个委托对象也可当作这个方法使用。delegate关键字定义的委托类型名称是MyDel,创建该委托类型的对象,其对象被初始化后拥有方法调用列表,分析过程如图7.3所示。

     
    (点击查看大图)图7.3  委托的分析图
  • 相关阅读:
    MacOS Sierra允许运行任何来源的程序
    Windows Server2008 R2中的角色
    Linux根目录解析
    Linux安装配置SVN服务器
    Linux6.x修改出eth0网卡的解决方法
    如何利用mount命令挂载另一台服务器上的目录
    Arcgis水文分析-Dem提取集水区
    前端布局之Flex布局
    其实我就是想好好的写写代码(一个伪程序猿的独白)
    WebApi关于配置全局返回Json数据格式时间以及命名小写
  • 原文地址:https://www.cnblogs.com/dudu837/p/1557282.html
Copyright © 2011-2022 走看看