@@ -100,7 +100,7 @@ private void PreProcessSignature()
100100 /// Since multicast delegate's built-in chaining supports only chaining instances of the same type,
101101 /// we need to complement this design by using an explicit linked list data structure.
102102 /// </summary>
103- private DelegateWrapper [ ] _delegateWrappers = Array . Empty < DelegateWrapper > ( ) ;
103+ private List < DelegateWrapper > _delegateWrappers = new List < DelegateWrapper > ( ) ;
104104
105105 private readonly int _dispid ;
106106 private ComEventsMethod ? _next ;
@@ -157,15 +157,15 @@ public bool Empty
157157 {
158158 get
159159 {
160- DelegateWrapper [ ] wrappers = _delegateWrappers ;
161- return wrappers . Length == 0 ;
160+ List < DelegateWrapper > wrappers = _delegateWrappers ;
161+ return wrappers . Count == 0 ;
162162 }
163163 }
164164
165165 public void AddDelegate ( Delegate d , bool wrapArgs = false )
166166 {
167- DelegateWrapper [ ] wrappers ;
168- DelegateWrapper [ ] newWrappers ;
167+ List < DelegateWrapper > wrappers ;
168+ List < DelegateWrapper > newWrappers ;
169169 do
170170 {
171171 wrappers = _delegateWrappers ;
@@ -180,25 +180,26 @@ public void AddDelegate(Delegate d, bool wrapArgs = false)
180180 }
181181 }
182182
183- newWrappers = new DelegateWrapper [ wrappers . Length + 1 ] ;
184- wrappers . CopyTo ( newWrappers , 0 ) ;
183+ newWrappers = wrappers . Count == 0
184+ ? new List < DelegateWrapper > ( )
185+ : wrappers . GetRange ( 0 , wrappers . Count ) ;
185186
186- newWrappers [ newWrappers . Length - 1 ] = new DelegateWrapper ( d , wrapArgs ) ;
187+ newWrappers . Add ( new DelegateWrapper ( d , wrapArgs ) ) ;
187188 } while ( ! PublishNewWrappers ( newWrappers , wrappers ) ) ;
188189 }
189190
190191 public void RemoveDelegate ( Delegate d , bool wrapArgs = false )
191192 {
192- DelegateWrapper [ ] wrappers ;
193- DelegateWrapper [ ] newWrappers ;
193+ List < DelegateWrapper > wrappers ;
194+ List < DelegateWrapper > newWrappers ;
194195 do
195196 {
196197 wrappers = _delegateWrappers ;
197198
198199 // Find delegate wrapper index
199200 int removeIdx = - 1 ;
200201 DelegateWrapper ? wrapper = null ;
201- for ( int i = 0 ; i < wrappers . Length ; i ++ )
202+ for ( int i = 0 ; i < wrappers . Count ; i ++ )
202203 {
203204 DelegateWrapper wrapperMaybe = wrappers [ i ] ;
204205 if ( wrapperMaybe . Delegate . GetType ( ) == d . GetType ( ) && wrapperMaybe . WrapArgs == wrapArgs )
@@ -223,22 +224,22 @@ public void RemoveDelegate(Delegate d, bool wrapArgs = false)
223224 return ; // No need to update collection
224225 }
225226
226- newWrappers = new DelegateWrapper [ wrappers . Length - 1 ] ;
227- wrappers . AsSpan ( 0 , removeIdx ) . CopyTo ( newWrappers ) ;
228- wrappers . AsSpan ( removeIdx + 1 ) . CopyTo ( newWrappers . AsSpan ( removeIdx ) ) ;
227+ newWrappers = wrappers . GetRange ( 0 , wrappers . Count ) ;
228+ newWrappers . RemoveAt ( removeIdx ) ;
229229 } while ( ! PublishNewWrappers ( newWrappers , wrappers ) ) ;
230230 }
231231
232232 public void RemoveDelegates ( Func < Delegate , bool > condition )
233233 {
234- DelegateWrapper [ ] wrappers ;
235- DelegateWrapper [ ] newWrappers ;
234+ List < DelegateWrapper > wrappers ;
235+ List < DelegateWrapper > newWrappers ;
236236 do
237237 {
238238 wrappers = _delegateWrappers ;
239239
240+ // Find delegate wrapper indexes. Iterate in reverse such that the list to remove is sorted by high to low index.
240241 List < int > toRemove = new List < int > ( ) ;
241- for ( int i = 0 ; i < wrappers . Length ; i ++ )
242+ for ( int i = wrappers . Count - 1 ; i >= 0 ; i -- )
242243 {
243244 DelegateWrapper wrapper = wrappers [ i ] ;
244245 Delegate [ ] invocationList = wrapper . Delegate . GetInvocationList ( ) ;
@@ -265,43 +266,20 @@ public void RemoveDelegates(Func<Delegate, bool> condition)
265266 return ;
266267 }
267268
268- newWrappers = RemoveAll ( wrappers , CollectionsMarshal . AsSpan ( toRemove ) ) ;
269- } while ( ! PublishNewWrappers ( newWrappers , wrappers ) ) ;
270-
271- // The list of indices is assumed to be sorted in ascending order
272- static DelegateWrapper [ ] RemoveAll ( DelegateWrapper [ ] oldCol , ReadOnlySpan < int > toRemove )
273- {
274- // Allocate new collection
275- var newCol = new DelegateWrapper [ oldCol . Length - toRemove . Length ] ;
276- if ( newCol . Length == 0 )
277- {
278- return newCol ;
279- }
280-
281- // Iterate over collection, skipping elements that should be removed.
282- int ri = 0 ;
283- for ( int oi = 0 , ni = 0 ; oi < oldCol . Length ; oi ++ )
269+ newWrappers = wrappers . GetRange ( 0 , wrappers . Count ) ;
270+ foreach ( int idx in toRemove )
284271 {
285- if ( ri < toRemove . Length && oi == toRemove [ ri ] )
286- {
287- ri ++ ;
288- continue ;
289- }
290-
291- newCol [ ni ] = oldCol [ oi ] ;
292- ni ++ ;
272+ newWrappers . RemoveAt ( idx ) ;
293273 }
294-
295- return newCol ;
296- }
274+ } while ( ! PublishNewWrappers ( newWrappers , wrappers ) ) ;
297275 }
298276
299277 public object ? Invoke ( object [ ] args )
300278 {
301279 Debug . Assert ( ! Empty ) ;
302280 object ? result = null ;
303281
304- DelegateWrapper [ ] wrappers = _delegateWrappers ;
282+ List < DelegateWrapper > wrappers = _delegateWrappers ;
305283 foreach ( DelegateWrapper wrapper in wrappers )
306284 {
307285 result = wrapper . Invoke ( args ) ;
@@ -311,7 +289,7 @@ static DelegateWrapper[] RemoveAll(DelegateWrapper[] oldCol, ReadOnlySpan<int> t
311289 }
312290
313291 // Attempt to update the member wrapper field
314- private bool PublishNewWrappers ( DelegateWrapper [ ] newWrappers , DelegateWrapper [ ] currentMaybe )
292+ private bool PublishNewWrappers ( List < DelegateWrapper > newWrappers , List < DelegateWrapper > currentMaybe )
315293 {
316294 return Interlocked . CompareExchange ( ref _delegateWrappers , newWrappers , currentMaybe ) == currentMaybe ;
317295 }
0 commit comments