C#中函数指针

c# 中,取消了c和c++中使用最灵活,也是最难掌握的指针。那么在c#中如何提供c/c++中的函数指针的功能?c#提供了委托(delegate),委托是继承自System.Delegate类的引用类型。它相当于函数指针原型。与函数指针不同的是,委托在c#中是类型安全的,委托特别适合于匿名调用。要使用委托需经过三个步骤,即声明、实例化、调用。
    using System;
    //声明一个名为mfDelegate的委托,该委托有一个string类型的参数
    //c#编译器编译时会产生一个新类,该类继承自System.Delegate,类
    //名为mfDelegate
    public delegate void mfDelegate(string name);
   
    public class Hello Word
    {
    //定义与mfDelegate有相同参数类型的方法Hello()
    public static void Hello(string name)
    {
    Console.WriteLine("您好,{0}!",name);
    }
    //定义与mfDelegate有相同参数类型的方法GoodBye()
    public static void GoodBye(string name)
    {
    Console.WriteLine("再见,{0}!",name);
    }
    public static void Main()
    {
    //创建一个mfDelegate实例 mf1
    mfDelegate mf1=new mfDelegate(Hello);
    //调用mf1
    mf1("Hello Word");
    mfDelegate mf2=new mfDelegate(GoodBye);
    mf2("Hello Word");
    //将mf1 mf2组合成一个新的委托mf3
    mfDelegate mf3=mf1+mf2;
    //调用mf3
    mf3("程序员");
    //从组合的委托mf3中删除mf1
    mfDelegate mf4=mf3-mf1;
    mf4("Hello Word");
    }
    }
 

 程序结果:您好,Hello Word!//mf1; 再见,Hello Word!//mf2
   您好,程序员! 再见,程序员!//mf3
   再见,Hello Word!//mf4

 

 

函数指针也叫指向函数的指针,它是为了提高函数的通用性而引入的。比较传统的方法是在函数中增加参数,通过增加的参数来判断到底要用什么函数,这样的缺点是灵活性差,为了支持多种方法要在函数中要写很多分支判断语句。比如,你要计算一个函数值(如sin x,log10 x)的平方,按照传统的方法你可以这样写这个函数:


public double Fuction(double Param,int FunctionSelection)
{
if(FunctionSelection=0)
   return Math.Pow(Math.Sin(Param),2);
if(FunctionSelection=1)
   return Math.Pow(Math.Log10(Param),2);
..............
}


显然,这种方法很费事,造成函数体很长。所以,函数指针的思想很重要。大家可能很熟悉C++中的DDP函数指针类型,那么,在完全面向对象的C#语言中函数指针是什么样子的呢?

在C#中我们使用delegate(委托)关键字来实现函数指针。
在《.NET Framework Essential》中有一个经典的例子:

using System;
namespace testDelegate
{
public class testDelegate
{
//1.定义回调函数指针.
delegate void MsgHandler(string strMsg);
//2.定义回调函数.
void OnMsg(string strMsg)
{
Console.WriteLine(strMsg);
}
public static void Main()
{
testDelegate t=new testDelegate();
//3.连接函数指针对象f到t.OnMsg.
MsgHandler f=new MsgHandler(t.OnMsg);
//4.调用指针的回调函数
f("Hello,Delegate!");
}
}
}

上面的例子注释说明了实现函数指针所要做的工作,我们发现在delegate void MsgHandler(string strMsg)一句中的参数是字符串型的,说明能够指向的函数也必须只有一个字符串参数,而MsgHandler f=new MsgHandler(t.OnMsg);中是把t.OnMsg这个函数直接传递给f。这个例子过于简单,但是已经说明函数指针的用法。我们不妨解决一下前面提出的计算不同函数值的平方的问题。

首先定义一个函数委托(指针):

delegate double DoubleHandler(double D_Parm);

这相当于在C++定义函数指针类型。

第二步定义回调函数就免了,因为我们可以使用Math.Sin函数和Math.Log10函数,但是我们必须定义一个函数来求平方:

public static double MathMethod(double parm1)
{
return Math.Pow(parm1,2);
}

这个函数和前面那个加参数的函数相比简单多了,但更具有通用性。

下面要做的就是要给前面定义的函数指针类型(即函数委托)建立对象并对其用函数将它初始化了:

DoubleHandler DoubleMethod=new DoubleHandler(Math.Sin);

大家已经看到了,这个指针指向了Math.Sin函数,相当于C++中的完成了对函数指针类型的“赋值”(初始化)。大家也可以通过添加DoubleMethod=new DoubleHandler(Math.Log10);重新初始化来改变函数指针的指向的函数对象。

最后就是计算函数值的平方了:

double d=MathMethod(DoubleMethod(.5);

以下是完整的程序,在Visual Studio.NET 2003下调试通过:

using System;

namespace testDelegate
{
public class testDelegate
{
   delegate void MsgHandler(string strMsg);
   delegate double DoubleHandler(double D_Parm);

   void OnMsg(string strMsg)
   {
    Console.WriteLine("The result is:/t{0}",strMsg);
   }

   public static double MathMethod(double parm1)
   {
    return Math.Pow(parm1,2);
   }

   public static void Main()
   {
    testDelegate t=new testDelegate();
    MsgHandler f=new MsgHandler(t.OnMsg);

    DoubleHandler[] DoubleMethod={
     new DoubleHandler(Math.Sin),
     new DoubleHandler(Math.Log10),
     new DoubleHandler(Math.Sqrt)
     };
    foreach(DoubleHandler handle in DoubleMethod)
    {
     f(MathMethod(handle(.5)).ToString()); //调用MsgHandler的对象f来显示计算结果
    }
   }
}
}

 

大部分转自:http://hi.baidu.com/liaowuhen2/blog/item/e5877d43635d00179213c612.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值