Explorar o código

Implement event handler list according to MS definition

svn path=/trunk/mcs/; revision=67455
Andrew Skiba %!s(int64=19) %!d(string=hai) anos
pai
achega
72d2aae2e2

+ 7 - 0
mcs/class/System/System.ComponentModel/ChangeLog

@@ -1,3 +1,10 @@
+2006-10-05 Andrew Skiba <[email protected]>
+
+	* EventHandlerList.cs: Implement event handler list according to MS
+	definition. No hash table, just a simple list with good performance
+	for a small number of events (<20) and worse performance when number
+	of events is bigger (patch by [email protected]).
+
 2006-10-29 Alexander Olk <[email protected]>
 
 	* ComponentResourceManager.cs: Make ApplyResources work.

+ 40 - 15
mcs/class/System/System.ComponentModel/EventHandlerList.cs

@@ -46,14 +46,13 @@ namespace System.ComponentModel {
 		
 		public EventHandlerList ()
 		{
+			head = null;
 		}
 
 		public Delegate this [object key] {
 			get {
-				if (table == null)
-					return null;
-
-				return table [key] as Delegate;
+				ListNode entry = FindEntry (key);
+				return entry == null ? null : entry.value;
 			}
 
 			set {
@@ -63,28 +62,54 @@ namespace System.ComponentModel {
 
 		public void AddHandler (object key, Delegate value)
 		{
-			if (table == null)
-				table = new Hashtable ();
-
-			Delegate prev = table [key] as Delegate;
-			prev = Delegate.Combine (prev, value);
-			table [key] = prev;
+			ListNode entry = FindEntry (key);
+			if (entry == null) {
+				head = new ListNode (key, value, head);
+				return;
+			}
+			entry.value = Delegate.Combine (entry.value, value);
 		}
 
 		public void RemoveHandler (object key, Delegate value)
 		{
-			if (table == null)
+			ListNode entry = FindEntry (key);
+			if (entry == null)
 				return;
 
-			Delegate prev = table [key] as Delegate;
-			prev = Delegate.Remove (prev, value);
-			table [key] = prev;
+			entry.value = Delegate.Remove (entry.value, value);
 		}
 
 		public void Dispose ()
 		{
-			table = null;
+			head = null;
+		}
+		private ListNode FindEntry (object key)
+		{
+			if (key == null)
+				throw new ArgumentNullException ("key", "Attempted lookup for a null key.");
+
+			for (ListNode entry = head; entry != null; entry = entry.next)
+				if (key == entry.key)
+					return entry;
+			return null;
 		}
+
+		[Serializable]
+		private class ListNode
+		{
+			public object key;
+			public Delegate value;
+			public ListNode next;
+			public ListNode (object key, Delegate value, ListNode next)
+			{
+				this.key = key;
+				this.value = value;
+				this.next = next;
+			}
+		}
+
+		private ListNode head;
+
 	}
 	
 }