日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

Effective C# 原则35:选择重写函数而不是使用事件句柄(译)

發布時間:2023/12/9 C# 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Effective C# 原则35:选择重写函数而不是使用事件句柄(译) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Effective C# 原則35:選擇重寫函數而不是使用事件句柄
Item 35: Prefer Overrides to Event Handlers

很多.Net類提供了兩種不同的方法來控制一些系統的事件。那就是,要么添加一個事件句柄;要么重寫基類的虛函數。為什么要提供兩個方法來完成同樣的事情呢?其實很簡單,那就是因為不同的情況下要調用為的方法。在派生類的內部,你應該總是重寫虛函數。而對于你的用戶,則應該限制他們只使用句柄來響應一些不相關的對象上的事件。

例如你很了一個很不錯的Windows應用程序,它要響應鼠標點下的事件。在你的窗體類中,你可以選擇重寫OnMouseDown()方法:

public class MyForm : Form
{

? // Other code elided.

? protected override void OnMouseDown(
??? MouseEventArgs e )
? {
??? try {
????? HandleMouseDown( e );
??? } catch ( Exception e1 )
??? {
????? // add specific error handling here.
??? }
??? // *almost always* call base class to let
??? // other event handlers process message.
??? // Users of your class expect it.
??? base.OnMouseDown( e );
? }
}

或者你可以添加一個事件句柄:


public class MyForm : Form
{

? // Other code elided.

? public MyForm( )
? {
??? this.MouseDown += new
????? MouseEventHandler( this.MouseDownHandler );
? }

? private void MouseDownHandler( object sender,
??? MouseEventArgs e )
? {
??? try {
????? HandleMouseDown( e );
??? } catch ( Exception e1 )
??? {
????? // add specific error handling here.
??? }
? }
}

前面一些方法要好一些,如果在事件鏈上有一個句柄拋出了一個異常,那么其它的句柄都不會再被調用(參見原則21)。一些“病態”的代碼會阻止系統調用事件上的句柄。通過重寫受保護的虛函數,你的控制句柄會就先執行。基類上的虛函數有責任調用詳細事件上的所有添加的句柄。這就是說,如果你希望事件上的句柄被調用(而且這是你最想完成的),你就必須調用基類。而在一些罕見的類中,你希望取代基類中的默認事件行為,這樣可以讓事件上的句柄都不被執行。你不去保證所所的事件句柄都將被調用,那是因為一些“病態”事件句柄可能會引發一些異常,但你可以保證你派生類的行為是正確的。

使用重載比添加事件句柄更高效。我已經在原則22中告訴過你,System.Windows.Forms.Control類是如何世故的使用任命機制來存儲事件句柄,然后映射恰當的句柄到詳細的事件上。這種事件機制要花上更多的處理器時間,那是因為它必須檢測事件,看它是否有事件句柄添加在上面。如果有,它就必須迭代整個調用鏈表。方法鏈表中的每個方法都必須調用。斷定有哪些事件句柄在那里,還要對它們進行運行時迭代,這與只調用一個虛函數來說,要花上更多的執行時間。

如果這還不足以讓你決定使用重載,那就再看看這一原則一開始的鏈表。那一個更清楚?如果重載虛函數,當你在維護這個窗體時,只有一個函數要檢查和修改。而事件機制則有兩個地方要維護:一個就是事件句柄,另一就是事件句柄上的函數。任何一個都可能出現失敗。就一個函數更簡單一些。

OK,我已經給出了所有要求使用重載而不是事件句柄的原因。.Net框架的設計者必須要添加事件給某人,對嗎?當然是這樣的。就你我們剩下的內容一個,他們太忙了而沒時間寫一些沒人使用的代碼。重寫只是為派生類提供的,其它類必須使用事件機制。例如,你經常添加一個按鈕點擊事件到一個窗體上。事件是由按鈕觸發的,但是由窗體對象處理著事件。你完全可以在這個類中定義一個用戶的按鈕,而且重寫這個點擊句柄,但這對于只是處理一個事件來說花上了太多的代碼。不管怎樣,問題都是交給你自己的類了:你自己定義的按鈕還是在點擊時必須與窗體進行通信。顯然應該用事件來處理。因此,最后,你只不過是創建了一個新類來向窗體發送事件(譯注:其實我們完全可以創建這個類不用發事件給窗體就可以完成回調的,只是作者習慣的說什么好就一味的否定其它。但不管怎樣,重寫一個按鈕來重載函數確實不是很值。)。 相對前面一種方法,直接在窗體事件添加句柄要簡單得多。這也就是為什么.Net框架的設計者把事件放在窗體的最前面。

另一個要使用事件的原因就是,事件是在運行時處理的。使用事件有更大的伸縮性。你可以在一個事件上添加多個句柄,這取決于程序的實際環境。假設你寫了一個繪圖程序,根據程序的狀態,鼠標點下時應該畫一條線,或者這它是要選擇一個對象。當用戶切換功能模式時,你可以切換事件句柄。不同的類,有著不同的事件句柄,而處理的事件則取決于應用程序的狀態。

最后,對于事件,你可以把多個事件句柄掛到同樣的事件上。還是想象同樣的繪圖程序,你可能在MouseDown事件上掛接了多個事件句柄。第一個可能是完成詳細的功能,第二個可能是更新狀態條或者更新一些可訪問的不同命令。不同的行為可以在同一事件上響應。

當你有一個派生類中只有一個函數處理一個事件時,重載是最好的方法。這更容易維護,今后也會更正確,而且更高效。而應該為其它用戶保留事件。因此,我們應該選擇重寫基類的實現而不是添加事件句柄。
=======================
???

Item 35: Prefer Overrides to Event Handlers
Many .NET classes provide two different ways to handle events from the system. You can attach an event handler, or you can override a virtual function in the base class. Why provide two ways of doing the same thing? Because different situations call for different methods, that's why. Inside derived classes, you should always override the virtual function. Limit your use of the event handlers to responding to events in unrelated objects.

You write a nifty Windows application that needs to respond to mouse down events. In your form class, you can choose to override the OnMouseDown() method:

public class MyForm : Form
{

? // Other code elided.

? protected override void OnMouseDown(
??? MouseEventArgs e )
? {
??? try {
????? HandleMouseDown( e );
??? } catch ( Exception e1 )
??? {
????? // add specific error handling here.
??? }
??? // *almost always* call base class to let
??? // other event handlers process message.
??? // Users of your class expect it.
??? base.OnMouseDown( e );
? }
}

?

Or, you could attach an event handler:

public class MyForm : Form
{

? // Other code elided.

? public MyForm( )
? {
??? this.MouseDown += new
????? MouseEventHandler( this.MouseDownHandler );
? }

? private void MouseDownHandler( object sender,
??? MouseEventArgs e )
? {
??? try {
????? HandleMouseDown( e );
??? } catch ( Exception e1 )
??? {
????? // add specific error handling here.
??? }
? }
}

?

The first method is preferred. If an event handler throws an exception, no other handlers in the chain for that event are called (see Item 21). Some other ill-formed code prevents the system from calling your event handler. By overriding the protected virtual function, your handler gets called first. The base class version of the virtual function is responsible for calling any event handlers attached to the particular event. That means that if you want the event handlers called (and you almost always do), you must call the base class. In some rare cases, you will want to replace the default behavior instead of calling the base class version so that none of the event handlers gets called. You can't guarantee that all the event handlers will be called because some ill-formed event handler might throw an exception, but you can guarantee that your derived class's behavior is correct.

Using the override is more efficient than attaching the event handler. I showed you in Item 22 how the System.Windows.Forms.Control class uses a sophisticated collection mechanism to store event handlers and map the appropriate handler to a particular event. The event-handling mechanism takes more work for the processor because it must examine the event to see if any event handlers have been attached. If so, it must iterate the entire invocation list. Each method in the event invocation list must be called. Determining whether there are event handlers and iterating each at runtime takes more execution time than invoking one virtual function.

If that's not enough for you, examine the first listing in this item again. Which is clearer? Overriding a virtual function has one function to examine and modify if you need to maintain the form. The event mechanism has two points to maintain: the event handler function and the code that wires up the event. Either of these could be the point of failure. One function is simpler.

Okay, I've been giving all these reasons to use the overrides and not use the event handlers. The .NET Framework designers must have added events for a reason, right? Of course they did. Like the rest of us, they're too busy to write code nobody uses. The overrides are for derived classes. Every other class must use the event mechanism. For example, you often add a button click handler in a form. The event is generated by the button, but the form object handles the event. You could define a custom button and override the click handler in that class, but that's way too much work to handle one event. It only moves the problem to your own class anyway: Somehow, your custom button must communicate to the form that the button was clicked. The obvious way to handle that is to create an event. So, in the end, you have created a new class to send an event to the form class. It would be simpler to just attach the form's event handler to the form in the first place. That's why the .NET Framework designers put those events in the forms in the first place.

Another reason for the event mechanism is that events are wired up at runtime. You have more flexibility using events. You can wire up different event handlers, depending on the circumstances of the program. Suppose that you write a drawing program. Depending on the state of the program, a mouse down might start drawing a line, or it might select an object. When the user switches modes, you can switch event handlers. Different classes, with different event handlers, handle the event depending on the state of the application.

Finally, with events, you can hook up multiple event handlers to the same event. Imagine the same drawing program again. You might have multiple event handlers hooked up on the MouseDown event. The first would perform the particular action. The second might update the status bar or update the accessibility of different commands. Multiple actions can take place in response to the same event.

When you have one function that handles one event in a derived class, the override is the better approach. It is easier to maintain, more likely to be correct over time, and more efficient. Reserve the event handlers for other uses. Prefer overriding the base class implementation to attaching an event handler.
?
???

???

轉載于:https://www.cnblogs.com/WuCountry/archive/2007/03/26/688983.html

總結

以上是生活随笔為你收集整理的Effective C# 原则35:选择重写函数而不是使用事件句柄(译)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。