C# 的 delegate 在创建实例时一定要new吗? 为什么我不new也可以啊?如下语句: [ComVisible(true)]
public class EventDisp
{
public EventDisp( FnEvent fnEvent)
{
_fnEvent = fnEvent ;//注意这里没有用 new FnEvent( fnEvent ) 的方法
}
#region Private Variable
public delegate void FnEvent();
FnEvent _fnEvent;
#endregion IHTMLDocument2 _doc2;
[DispId(0)]
public void Event()
{
_fnEvent();
}
}创建一个IDispatch的对象, 构造函数接受一个函数指针.
然后我调用的时候是这样干的:
Document2.onclick = new EventDisp( _OnClick );
程序也完全正常,没有发生问题.所以我很疑惑,为啥?
谢谢大家!
public class EventDisp
{
public EventDisp( FnEvent fnEvent)
{
_fnEvent = fnEvent ;//注意这里没有用 new FnEvent( fnEvent ) 的方法
}
#region Private Variable
public delegate void FnEvent();
FnEvent _fnEvent;
#endregion IHTMLDocument2 _doc2;
[DispId(0)]
public void Event()
{
_fnEvent();
}
}创建一个IDispatch的对象, 构造函数接受一个函数指针.
然后我调用的时候是这样干的:
Document2.onclick = new EventDisp( _OnClick );
程序也完全正常,没有发生问题.所以我很疑惑,为啥?
谢谢大家!
上提到了“简化语法”。我第一次看到简化语法的时候,想“这样是不是就比new一个实例更快了?”,于是就去求证了一下。20分钟后发现,原来是一样的。
factorial = n =>
{
if (n == 0)
return 1;
else
return n * factorial(n - 1);
};这里为factorial赋值为null,然后的赋值其实是用一个匿名函数做参数来创建Fun<int,int>类型的一个对象,这个函数使用了lamda表达式。求9的阶乘就是int result=factorial(9);
使用关键字event可以让编译器帮我们限制事件(一种特殊的delegate)调用写法。事件实例必须声明在类型范畴(而不是方法内部),它只能使用 += 和 -= 之类的写法。
它定义一个“一个输入参数arg的类型为T,输出类型为TResult”的delegate。由于使用泛型,那么在实际定义类似类型时直接从泛型映射为类型(将泛型的类型参数赋值为具体类型)就可以了,而不再需要逐一定义具体的类型。所以我使用 Func<int,int> 来声明 factorial 的类型。委托有 Combine 方法。例如Func<int, int> factorial = null;
factorial = n =>
{
if (n == 0)
return 1;
else
return n * factorial(n - 1);
};
factorial += n => n * 10;
这最后一句就被编译器编译为factorial = (Func<int, int>) Delegate.Combine(factorial, n => n * 10);
它把原来的factorial实例跟新的匿名方法(c#所支持的lamda表达式允许对于只有一行的函数省略return关键字)合并起来,然后将合并得到的新实例再赋值给factorial。实际上我们在为事件注册处理方法时看到的也就是这个Combine操作。不过这个例子运行,就会发现 factorial(9) 只是返回90,而不再是阶乘了。这是因为合并过多个delegate的最终delegate运行时实际上仍然执行了所有delegate,可是它的返回值仅仅被最后一个delegate调用方法的返回值反映出来。在我们触发事件时,如果服务要从客户程序获取一些资料,但是有多个客户程序都注册了对这个服务对象的这个事件进行处理,结果服务事件就只能得到最后一个处理程序的结果。要想手动地去执行每一个方法也不难,只要这样调用delegate:foreach (Func<int,int> f in factorial.GetInvocationList())
Console.WriteLine(f(9));这样就可以细致地逐一调用每一个delegate。