命名方法与匿名方法总结(转载)

 
命名方法
委托可以与命名方法关联。使用命名的方法对委托进行实例化时,该方法将作为参数传递,例如:
// Declare a delegate:
delegate void Del(int x);//定义一委托(注意下面的签名)
// Define a named method:
void DoWork(int k) { /* ... */ }
// Instantiate the delegate using the method as a parameter:
Del d = obj.DoWork;//使用命名方法名为参数给委托初始化
这被称为使用命名的方法。使用命名方法构造的委托可以封装   静态方法或实例方法。在以前的 C# 版本中,使用命名的方法是对委托进行实例化的唯一方式。但是,在创建新方法的系统开销不必要时,C# 2.0 允许您对委托进行实例化,即在创建委托对象的时候立即指定该委托对象在被调用时处理的代码块。这些被称为 匿名方法。
作为委托参数传递的方法必须与委托声明具有相同的签名。委托实例可以封装静态或实例方法。
尽管委托可以使用 out 参数,但不推荐将其用于多路广播事件委托中,因为无法确定要调用哪个委托。
示例 1
以下是声明及使用委托的一个简单示例。注意,委托 Del 和关联的方法 MultiplyNumbers 具有相同的签名
// Declare a delegate
delegate void Del(int i, double j);// 签名是指:委托类型的返回类型、参数个数、参数类型
class MathClass
{
    static void Main()
    {
        MathClass m = new MathClass();//m:MathClass类一对象
         // Delegate instantiation using "MultiplyNumbers"
        Del d = m.MultiplyNumbers;//委托实例化封装MultiplyNumbers方法
         // Invoke the delegate object.
         System.Console.WriteLine("Invoking the delegate using 'MultiplyNumbers':");
          for (int i = 1; i <= 5; i++)
          {
               d(i, 2);//调用
}
    }

          // Declare the associated method.定义一个与上面委托相关联的方法
void MultiplyNumbers(int m, double n)
{
  System.Console.Write(m * n + " ");
}

}
输出
Invoking the delegate using 'MultiplyNumbers':
2 4 6 8 10


示例 2
在下面的示例中,一个委托被同时映射到静态方法和实例方法,并分别返回特定的信息。
// Declare a delegate
delegate void Del();私有的无返回值的无参数的委托类型
class SampleClass
{
          //在该类中声明两个方法

public void InstanceMethod()
{
   System.Console.WriteLine("A message from the instance method.");
}
static public void StaticMethod()
{
   System.Console.WriteLine("A message from the static method.");
}
}
class TestSampleClass
{
static void Main()
{
    SampleClass sc = new SampleClass();

// Map the delegate to the instance method:
Del d = sc.InstanceMethod;
d();
// Map to the static method:
d = SampleClass.StaticMethod;
d();
}
}
输出
A message from the instance method.
A message from the static method.
终于明白了

匿名方法
在 2.0 之前的 C# 版本中,声明 委托的唯一方法是使用 命名方法。C# 2.0 引入了匿名方法。
要将代码块传递为委托参数,创建匿名方法则是唯一的方法。例如:
// Create a handler for a click event 事件
button1.Click += delegate(System.Object o, System.EventArgs e)
{ System.Windows.Forms.MessageBox.Show("Click!"); };

C#
// Create a delegate instance
delegate void Del(int x);

// Instantiate the delegate using an anonymous method
Del d = delegate(int k) { /* ... */ };
如果使用匿名方法,则不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。
例如,如果创建方法所需的系统开销是不必要的,在委托的位置指定代码块就非常有用。启动新线程即是一个很好的示例。无需为委托创建更多方法,线程类即可创建一个线程并且包含该线程执行的代码。
void StartThread()
{
           System.Threading.Thread t1 = new System.Threading.Thread(//使用匿名方法
            delegate(){
           System.Console.Write("Hello, ");
            System.Console.WriteLine("World!")}                                        );
         t1.Start();
}
匿名方法的参数的范围是 anonymous-method-block。

在目标在块外部的匿名方法块内使用跳转语句(如 goto、 break 或 continue)是错误的。在目标在块内部的匿名方法块外部使用跳转语句(如 goto、break 或 continue)也是错误的。

如果局部变量和参数的范围包含匿名方法声明,则该局部变量和参数称为该匿名方法的 外部变量或捕获变量。例如,下面代码段中的 n 即是一个外部变量:
int n = 0;
Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };
与局部变量不同,外部变量的生命周期一直持续到引用该匿名方法的委托符合垃圾回收的条件为止。对 n 的引用是在创建该委托时捕获的。
匿名方法不能访问外部范围的 ref 或 out 参数。
在 anonymous-method-block 中不能访问任何不安全代码。
下面的示例演示实例化委托的两种方法:
使委托与匿名方法关联。
使委托与命名方法 (DoWork) 关联。
两种方法都会在调用委托时显示一条消息。
// Declare a delegate
delegate void Printer(string s);
class TestClass
{
static void Main()
{
         // Instatiate the delegate type using an anonymous method://使用匿名方法
Printer p = delegate(string j){ System.Console.WriteLine(j);};
// Results from the anonymous delegate call:
p("The delegate using the anonymous method is called.");

// The delegate instantiation using a named method "DoWork":
p = new Printer(TestClass.DoWork);//使用命名方法实例化 委托对象p

// Results from the old style delegate call:
p("The delegate using the named method is called.");//调用p(命名方法)
}

// The method associated with the named delegate:
static void DoWork(string k)
{
  System.Console.WriteLine(k);
}
}

输出
The delegate using the anonymous method is called.
The delegate using the named method is called.

当使用了匿名方法的类里,CLR会自动生成一个跟调用命名方法时有同样签名的EventHandler和一个method来处理,所以,匿名方法只是减少了我们的编码量。
以下示例代码,欢迎大家批评指正:
C# Source Code:
......//引用命名空间
namespace HolyHouse
{
    class Program
   {
static void main(string[] args)//主函数(方法)
{
Person p = new Person("Holy");//初始化(实例化)Person类对象P
p.Say += delegate() { Console.WriteLine("Yeah. Where is my method?"); };//在P的事件Say上挂接一匿名方法(调用控制台输出)
Console.WriteLine(p.ToString());//调用P的ToString()方法
Console.Read();//输入任意值结束
}
    }
    class Person
    {
public event EventHandler Say;//事件(特殊委托)的声明方式
public string Name;
public Person(string name)
{
    Name = name;
}
protected virtual void OnSay(EventArgs e)//e对象中存放事件数据;本例中e是空数据集合(无事件数据)
{
 if(Say != null)//判断事件有没有挂接任意类型的方法
{
  Say(this, e);//调用事件;如果事件挂接了方法,则把e传递给方法
}
}
public override string ToString()//重写ToString()方法
{
     OnSay(EventArgs.Empty);//调用方法OnSay();EventArgs.Empty表示事件数据为空
     return string.Format("My name is {0}, thank you.", Name);
}
     }
}
Output:
Yeah.Where is my method?
My name is Holy, thank you.
在查看IL代码时可以看到,Program类里有一个名为<>9__CachedAnonymousMethodDelegate1的EventHandler和一个名为b__0的跟EventHandler的签名符合的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值