c#委托中另外一种用法
Posted 王小会
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#委托中另外一种用法相关的知识,希望对你有一定的参考价值。
在c#委托中,经常可能遇到函数重载的情况,可是又需要在一个函数中调用这些函数,一般我都是根据多个函数重载个数,也写上这么多个函数重载。比如
public double T1(int r) { return r; } public double T2(double n1, double n2) { return n1 + n2; }
现在呢,我需要写另外一个函数,这个函数第一个参数就是委托类型,我想让他既可以代表T1,也可以代表T2,但是一般是无法这样做的,因此我们只能写两个函数
public void DT1(Func<double,int> fun,double r) { Console.WriteLine("这是T1方法得到的结果:{0}",fun(r)); } public void DT1(Func<double,double,double>fun, double n1,double n2) { Console.WriteLine("这是T1方法得到的结果:{0}", fun(n1,n2)); }
当函数少的时候这样写还可以,一旦多了呢,或者根本不知道要传哪种类型的委托,这时候该怎么办,我们想到了多态,也就是传一个委托的父类,参数声明为object类型,比如:
public void T(Delegate d,object[] pms) { }
但是,这样该如何调用呢,我们首先想到那我能不能直接d(pms)呢, 答案肯定是不行的,如果你这样做,编译器就会提示:”“d”是“变量”,但此处被当做“方法”来使用”,为什么会出现这种情况,我们转到这个类的定义查看,发现Delegate是一个abstract 类,也就是只有在执行的过程中,CLR才会知道到底是d代表的是哪种委托,所以就无法这样做了~~。然后我们想到了反射,是不是可以利用反射呢。果然,这个类下面有一个属性 public MethodInfo Method { get; } 这个属性是一个MethodInfo类型的。于是我们这样改一下代码:
public void T(Delegate d,object[] pms) { //d(pms); double r = 0; System.Reflection.MethodInfo method = d.Method; r=(double)method.Invoke(this, pms); Console.WriteLine("Invoke得到的结果:{0}",r); }
invoke中的第一个参数是这个方法是哪个类的,如果是静态方法,则忽略此参数,第二个参数是一个object数组,代表了这个委托代表方法的参数,按顺序传递。Invoke方法的返回值就是执行方法的返回值,这里强转一下,就能得到结果。
static void Main(string[] args) { Test ct = new Test(); ct.T(new Func<int, double>(ct.T1), new object[] { 1 }); ct.T(new Func<double, double, double>(ct.T2), new object[] { 1, 2 }); Console.ReadKey(); }
执行结果为:
Invoke得到的结果:1 Invoke得到的结果:3
Delegate中还有一个方法,protected virtual object DynamicInvokeImpl(object[] args) 这是一个虚函数,和Invoke方法是一样的,只不过省略了第一个参数
public void T(Delegate d,object[] pms) { //d(pms); double r = 0; //System.Reflection.MethodInfo method = d.Method; //r=(double)method.Invoke(this, pms); r=(double)d.DynamicInvoke(pms); Console.WriteLine("Invoke得到的结果:{0}",r); }
这样也能达到同样的效果。
第一次写博客。。有的东西也是似懂非懂,还请各位大神见谅。。。
以上是关于c#委托中另外一种用法的主要内容,如果未能解决你的问题,请参考以下文章
对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段