一个关于Page_load诡异的问题!
如果我们按照Page_Load()去调用一样可以成功。代码如下:protected void Page_Load()
{
Response.Write("load1");
}
输出:load1
如果现在我们加上一个(page小写)
protected void page_Load()
{
Response.Write("load2");
}
结果输出:load2,也就是后面的函数覆盖了前面的。
我们再换下:
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("load1");
}
protected void page_Load()
{
Response.Write("load2");
}
应该输出什么,没错,又输出了load1;诡异之处,有两点:
1:不加(object sender, EventArgs e) 这两个参数,一样可以输出。
2:但是如果两个函数,一个加参数,一个不加,加的将覆盖不加的。后面将覆盖前面的。
同样的,对于 Page_preload()一样。
而且,用reflector反编译,你会发现,Page里面竟然没有load事件的定义。是有preLoad的定义。
更诡异的是,上述例子用VB竟然都通不过。
--------------------编程问答-------------------- 等待高手来讲其原由! --------------------编程问答-------------------- 以下抄自msdn
如果页面想要处理某个事件,它应该显式地注册相应的处理程序。然而,为了向后兼容早期的 Visual Basic 编程风格,ASP.NET 也支持一种隐式的事件挂起形式。在默认情况下,页面将尝试把特定的方法名与事件匹配起来;如果找到匹配的方法,就认为该方法是该事件的处理程序。ASP.NET 提供了六个方法名的特定识别。它们是 Page_Init、Page_Load、Page_DataBind、Page_PreRender 和 Page_Unload。这些方法被当作是 Page 类所提供的相应事件的处理程序。HTTP 运行时将自动把这些方法与页面事件绑定起来,这样一来,开发人员就不必编写所需的粘接代码。例如,名为 Page_Load 的方法与页面的 Load 事件绑定,就像已编写以下代码一样。
this.Load += new EventHandler(this.Page_Load);
在页面级上,以上所列的某些阶段是不可见的,并仅影响服务器控件编写者和那些凑巧要创建从 Page 派生的类的开发人员。页面向外界发送的活动信号仅包括 Init、Load、PreRender、Unload 以及嵌入式控件所定义的所有回发事件。
--------------------编程问答-------------------- 函数的重载引起的。 --------------------编程问答--------------------
“为了向后兼容早期的 Visual Basic 编程风格”但这个例子在VB中通不过。
如果两个函数,一个加参数,一个不加,加的将覆盖不加的。那又是为什么呢?
但是 protected void Page_Load(obejct sender)
{
Response.Write("load1");
}
就不过输出load1
protected void Page_Load()
就 可以。 --------------------编程问答-------------------- 这么心细 --------------------编程问答-------------------- ddd --------------------编程问答-------------------- hh --------------------编程问答-------------------- 先看看调用栈如下所示:
> WebApplication1.DLL!WebApplication1._Default.page_load() Line 24 C#
System.Web.RegularExpressions.dll!System.Web.Util.CalliHelper.ArglessFunctionCaller(System.IntPtr fp, object o) + 0x9 bytes
System.Web.dll!System.Web.Util.CalliEventHandlerDelegateProxy.Callback(object sender, System.EventArgs e) + 0x36 bytes
System.Web.dll!System.Web.UI.Control.OnLoad(System.EventArgs e) + 0x74 bytes
System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x32 bytes
> WebApplication1.DLL!WebApplication1._Default.Page_Load(object sender = {ASP.default_aspx}, System.EventArgs e = {System.EventArgs}) Line 15 C#
System.Web.RegularExpressions.dll!System.Web.Util.CalliHelper.EventArgFunctionCaller(System.IntPtr fp, object o, object t, System.EventArgs e) + 0xf bytes
System.Web.dll!System.Web.Util.CalliEventHandlerDelegateProxy.Callback(object sender, System.EventArgs e) + 0x24 bytes
System.Web.dll!System.Web.UI.Control.OnLoad(System.EventArgs e) + 0x74 bytes
System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x32 bytes
问题就在CalliEventHandlerDelegateProxy.Callback这个函数这里,调用这个函数首先应该实例化CalliEventHandlerDelegateProxy对象,这个对象是在哪实例化的?
这个对象是在页面的基类TemplateControl中的HookUpAutomaticHandlers方法被实例化的,这个方法最终决定调用哪个Load方法,代码如下:
internal void HookUpAutomaticHandlers() {
// Do nothing if auto-events are not supported
if (!SupportAutoEvents) {
return;
}
// Get the event list for this Type from our cache, if possible
object o = _eventListCache[GetType()];
IDictionary dictionary = null;
// Try to find what handlers are implemented if not tried before
if (o == null) {
lock (_lockObject) {
// Try the cache again, in case another thread took care of it
o = _eventListCache[GetType()];
if (o == null) {
dictionary = new ListDictionary();
GetDelegateInformation(dictionary);
// Cannot find any known handlers.
if (dictionary.Count == 0) {
o = _emptyEventSingleton;
}
else {
o = dictionary;
}
// Cache it for next time
_eventListCache[GetType()] = o;
}
}
}
// Don't do any thing if no known handlers are found.
if (o == _emptyEventSingleton) {
return;
}
dictionary = (IDictionary)o;
foreach (string key in dictionary.Keys) {
EventMethodInfo info = (EventMethodInfo)dictionary[key];
Debug.Assert(_eventObjects[key] != null);
bool eventExists = false;
MethodInfo methodInfo = info.MethodInfo;
Delegate eventDelegates = Events[_eventObjects[key]];
if (eventDelegates != null) {
foreach (Delegate eventDelegate in eventDelegates.GetInvocationList()) {
// Ignore if this method is already added to the events list.
if (eventDelegate.Method.Equals(methodInfo)) {
eventExists = true;
break;
}
}
}
if (!eventExists) {
// Create a new Calli delegate proxy
IntPtr functionPtr = methodInfo.MethodHandle.GetFunctionPointer();
EventHandler handler = (new CalliEventHandlerDelegateProxy(this, functionPtr, info.IsArgless)).Handler;
// Adds the delegate to events list.
Events.AddHandler(_eventObjects[key], handler);
}
}
}
--------------------编程问答-------------------- 楼上强人!
请问楼上是如何得到调用栈的代码的呢?
还有HookUpAutomaticHandlers的代码是如何找到的?
--------------------编程问答-------------------- 按照这么说,c#的运行效率似乎还不如VB,VB是直接进行代理handers me.load的 --------------------编程问答-------------------- 不知所云?!
protected void Page_Load(object sender, EventArgs e) 这是本身
{
Response.Write("load1");
page_Load();
}
protected void page_Load() 这是自定义
{
Response.Write("load2");
}
--------------------编程问答--------------------
是啊,但是你把第一个函数去掉,它一样可以运行Response.Write("load2");啊 --------------------编程问答-------------------- 楼上强人!
请问楼上是如何得到调用栈的代码的呢?
还有HookUpAutomaticHandlers的代码是如何找到的?
补充:.NET技术 , ASP.NET