提高事件,將調用其事件處理程序。例如http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx提高事件與直接方法調用差異
使用事件機制和直接調用其他方法(例如,如果在方法A()中調用條件,調用B())之間有什麼區別?
消費和舉辦活動有什麼區別?
感謝
提高事件,將調用其事件處理程序。例如http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx提高事件與直接方法調用差異
使用事件機制和直接調用其他方法(例如,如果在方法A()中調用條件,調用B())之間有什麼區別?
消費和舉辦活動有什麼區別?
感謝
引發事件,將調用其事件 處理
即開始了錯。可能有沒有事件處理程序。或許多。你不知道。這與直接調用方法的主要區別在於。在你喜歡的設計模式書中查找「觀察者模式」。
引發事件(或調用,使用從你的鏈接術語)意味着你發送事件給所有消費者。例如,窗口可以在用鼠標點擊時引發事件。
消費事件意味着您正在接收並處理髮送它的人的事件。例如,您可能想知道何時通過鼠標點擊窗口。
如果你只有一個消費者,那麼你可以完成的只是直接提供的回調類似的東西:
// 'Event' type:
delegate void DelMyEvent();
// consumer:
class Consumer
{
Producer _theProducer;
void RegisterForNotification()
{
_theProducer.OnMyEvent = new DelMyEvent(OnMyEvent);
}
void OnMyEvent() { }
}
// producer:
class Producer
{
public DelMyEvent OnMyEvent;
void SendNotification()
{
if(OnMyEvent != null) OnMyEvent();
}
}
事件機制通過阻止消費者從直接設置委託值清除這了一點。相反,它使消費者向+=
運營商註冊。當第一個消費者註冊時,代表被設置,當第二個消費者註冊時,他們的兩個回叫通過Delegate.Combine
鏈接在一起。
「如果你只有一個消費者,那麼你可以在原則上使用,而不是事件的委託」,爲什麼這是在事件選擇代表一個標準,甚至?許多人可以向代表註冊! – 2010-04-18 02:08:19
這篇文章是不正確的。 「事件」只是一種修飾詞,而不是一種類型。一個'事件'實際上是一個'代表',有一些額外的限制。不同的是,一個事件不會讓你直接設置它。 IE:'myDelegate = someOtherDelegate;'會給你一個錯誤。一個事件限制訪問,所以你只能使用'+ ='和' - ='運算符。代表也可以有一個調用列表。只要你願意,你可以''將盡可能多的'委託人'代入'代表'。就像你可以參加一個活動一樣。 – Joel 2010-04-18 03:02:41
你是對的。試圖修復破碎。 – Eric 2010-04-18 03:20:32
有什麼用 事件機制,直接調用 其他方法之間的差異(例如,如果一個條件在方法A()符合 ,調用B())?
商業邏輯明智兩者之間沒有區別。我的意思是,你可以在每個方面完成相同的任務。這只是一種不同的方式。真正的區別在於您爲處理其他模塊的通知所做的工作量。
隨着事件的發展,你基本上會說:「嘿,發生了一些代碼,在發生這種事情時已經註冊通知了,讓他們知道。哪些通知的模塊不是我關心的,因爲我我假設(在運行時)需要知道的所有模塊都已設置爲通知。「
通過直接調用每個方法,您決定要告訴這個(或這些)模塊,只有這些,發生了某些事情。你正在斷言,無論這些模塊的狀態如何不重要,他們都需要知道這個事件發生了。
兩者對於不同的情況都是正確的。事件通知更加動態。不同的模塊可以註冊並取消註冊通知。直接方法調用更加靜態。一些對象(或模塊等)絕對會被通知(除非有例外情況)發生了一些事情,但只有這些纔會被通知。
除了上面的multiple/no用戶場景外,事件也用於減少代碼耦合 - 例如,在編譯時,方法A()不需要知道有關方法B()的任何內容。這可以更好地分離關注點和較脆弱的代碼。
在野外,您更有可能看到框架和UI代碼中使用的事件,而在應用程序的域邏輯中,開發人員通常使用諸如Separated Interface和Dependency Injection之類的東西來解耦代碼。最近,在各領域中關於在領域邏輯中使用事件的討論有了更多的討論,這種巧妙命名爲Domain Events的方法。
雖然事件通常用於減少代碼耦合,但我認爲值得注意的是有時候情況並非如此。我偶爾會看到程序員使用事件而不是直接函數調用,因爲他們認爲它更好地分離關注點,即使事件顯然只用於一個位置來調用一個函數。你最終有兩個耦合的對象看起來像一個偶然觀察者的分離對象。 – tsiki 2013-07-11 11:36:55
的區別是這樣的:「如果有人傾聽和關心,這件事情就這樣發生了」
方法調用 =「做這個具體的事情」
事件提高 =
它是分離關注點和可重用性的核心。如果點擊它,則按鈕不是可重用組件,而是調用特定的方法。但如果它簡單地向程序「宣佈」它被點擊了,並且感興趣的各方負責訂閱它自己,它是無限可重用的。
這是如何完成(通過委託)的基本技術實現是無關緊要的。
對於任何對事件調用感興趣的人,我已經做出了這個簡單的基準。 它顯示了直接調用方法,通過接口調用它,通過委託和通過事件(其中附加了一個處理程序)之間的區別。
在每種情況下,該方法以相應的方式調用1 000 000 000次。這裏是(也許令人驚訝的)結果:
代表電話:23 240毫秒 - 最快
事件電話:23 295毫秒
直接撥打電話:23 396毫秒
界面撥打電話:23 716 ms - 最慢
這些測量是在.NET4.0中使用C#進行版本構建完成的。
的代碼是在這裏:
class Program
{
static void Main(string[] args)
{
TestClass.RunTest();
Console.ReadLine();
}
}
interface ITestClass
{
void TestMethod(object sender, TestEventArgs eventErgs);
}
class TestClass : ITestClass
{
#region Events
event EventHandler<TestEventArgs> TestEvent;
#endregion
#region Constructor
public TestClass()
{
TestEvent += TestMethod;
}
#endregion
#region Public Methods
public static void RunTest()
{
int testCount = 1000000000; //1 000 000 000
string format = "{0:### ### ### ##0}";
#region Direct Call
Console.WriteLine("Direct call");
TestClass testClass = new TestClass();
testClass.TestMethod(testClass, new TestEventArgs(3));
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < testCount; ++i)
{
testClass.TestMethod(testClass, new TestEventArgs(3));
}
stopwatch.Stop();
Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
Console.WriteLine();
#endregion
#region Interface Call
Console.WriteLine("Interface call");
ITestClass itestClass = new TestClass();
itestClass.TestMethod(testClass, new TestEventArgs(3));
stopwatch = Stopwatch.StartNew();
for (int i = 0; i < testCount; ++i)
{
itestClass.TestMethod(testClass, new TestEventArgs(3));
}
stopwatch.Stop();
Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
Console.WriteLine();
#endregion
#region Delegate Call
Console.WriteLine("Delegate call");
TestClass delegateTestClass = new TestClass();
Action<object, TestEventArgs> delegateMethod = delegateTestClass.TestMethod;
delegateMethod(testClass, new TestEventArgs(3));
stopwatch = Stopwatch.StartNew();
for (int i = 0; i < testCount; ++i)
{
delegateMethod(testClass, new TestEventArgs(3));
}
stopwatch.Stop();
Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
Console.WriteLine();
#endregion
#region Event Call
Console.WriteLine("Event call");
TestClass eventTestClast = new TestClass();
eventTestClast.TestEvent(testClass, new TestEventArgs(3));
stopwatch = Stopwatch.StartNew();
for (int i = 0; i < testCount; ++i)
{
eventTestClast.TestEvent(testClass, new TestEventArgs(3));
}
stopwatch.Stop();
Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
Console.WriteLine();
#endregion
}
#endregion
#region ITestClass Members
public void TestMethod(object sender, TestEventArgs e)
{
e.Result = e.Value * 3;
}
#endregion
}
class TestEventArgs : EventArgs
{
public int Value { get; private set; }
public int Result { get; set; }
public TestEventArgs(int value)
{
Value = value;
}
}
就是這樣!謝謝。 – dotnetdev 2010-04-18 17:04:51