面试例题4:举例说明匿名方法。
考点:匿名方法的作用,匿名方法的使用方法。
出现频率:★★★
解答
匿名方法用于简化事件注册方法的编写过程,可以直接将方法体的代码和委托对象相关联而不需要单独定义这个方法。本例程序仍然实现EventDel.cs的相同功能,只是将事件处理方法更改为匿名方法,并且在Name类中将触发事件的代码直接编写在Text属性的set访问器中。在目录下新建一个程序文件,并命名为AnoMethod.cs,编写代码如代码7.4所示。
代码7.4 C#的匿名方法:AnoMethod.cs
using System;
class AnoMethod { static void Main(string[] args) { //创建Name类的对象myname Name myname = new Name(); //向myname对象的Get事件注册匿名事件处理方法 myname.Get += delegate(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); }; Console.Write("\n请输入你的名字:"); //接收用户的输入值并赋值给input变量 string input = Console.ReadLine(); //将input变量赋值给myname对象的Text属性 myname.Text = input; } } 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.Get(this, new NameEventArgs("Text属性被更改了")); } } //重写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完全一样,用于显示用户输入,事件触发后调用匿名事件处理方法。在命令行下编译AnoMethod.cs,执行AnoMethod程序,程序将提示"请输入你的名字",输入"叶青",运行结果如图7.6所示。
|
(点击查看大图)图7.6 C#的匿名方法 |
本程序运行结果与EventDel.cs完全一致,只是匿名方法的编写更为高效。回顾List<T>对象的FindAll()方法,该方法的参数是一个泛型委托(委托类型为Predicate),编写方法如以下代码所示:
using System; using System..Collections.Generic //定义1个List<T>类的对象MyList ,类型参数T为int List<int> MyList = new List<int>(); 添加部分int类型子项到MyList 对象中; List<int> MyList2 = MyList2.FindAll(delegate(匹配方法参数){匹配方法体代码}); foreach (int i in MyList2) { 输出int子项i的信息; }
|
以上代码将Predicate泛型委托对象的编写进行了大量简化,不需要单独定义匹配方法。
注意:是否采用匿名方法根据情况来定,如某些方法体代码比较复杂,或者方法可用于委托对象以外时,不可以采用匿名方法。
解析
C#的匿名方法可以使委托及事件的代码编写更加精简高效。一般情况下,注册事件处理方法,首先需要定义处理方法,如果该方法仅用于订阅特定的事件,则可使用匿名方法。假设定义了名为MyDel委托类型,事件名称为onclick,其注册事件处理方法如以下代码所示:
static void Main(string[] args) { //定义MyDel委托类型 public delegate 返回类型 MyDel(object sender, EventArgs e); //定义onclick事件 public event MyDel onclick //事件处理方法订阅onclick事件 onclick+= new MyDel(事件处理方法); 其他代码; } //单独定义事件处理方法 static 返回类型 事件处理方法(object sender, EventArgs e) { 事件处理方法体代码; }
|
以上代码中的事件处理方法往往只用于委托对象,而匿名方法可以使事件处理方法不需要单独定义,如以下代码所示:
static void Main(string[] args) { //定义委托及关联事件 public delegate 返回类型 MyDel(object sender, EventArgs e); public event MyDel onclick //事件处理方法订阅onclick事件 onclick+= delegate(object sender, EventArgs e){事件处理方法体代码}; 其他代码; }
|
以上代码的事件处理方法没有名称,被称为匿名方法。匿名方法的方法体代码直接和委托对象关联,不需要指定委托对象名称。
说明:实际编译时,匿名方法的名称由编译器自动分配。
面试例题5:简述Lambda表达式的使用方法。
考点:Lambda表达式的作用, Lambda表达式的使用方法。
出现频率:★
解答
Lambda表达式可以进一步简化编写的代码,在匿名方法的基础上,甚至可以隐藏delegate关键字。不过Lambda表达式不可滥用,应根据程序需要而使用。本例程序仍然实现AnoMethod.cs相同的功能,只是将匿名方法部分更改为Lambda表达式。在目录下新建一个程序文件,并命名为Lambda.cs,编写代码如代码7.5所示。
代码7.5 C#的Lambda表达式:AnoMethod.cs
using System;
class Lambda { static void Main(string[] args) { //创建Name类的对象myname Name myname = new Name(); //向myname对象的Get事件注册匿名事件处理方法 myname.Get += (object sender, Name.NameEventArgs e)=> { Console.WriteLine("\n\t=========Lambda表达式========="); Console.WriteLine("事件信息:{0}", e.ToString()); Console.WriteLine("事件发布者是:{0}", sender.ToString()); Console.WriteLine("你输入的名字是:{0}", ((Name)sender).Text); }; Console.Write("\n请输入你的名字:"); //接收用户的输入值并赋值给input变量 string input = Console.ReadLine(); //将input变量赋值给myname对象的Text属性 myname.Text = input; } } 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.Get(this, new NameEventArgs("Text属性被更改了")); } } //重写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; } } }
|