5
5
using System ;
6
6
using System . Buffers ;
7
7
using System . Collections . Generic ;
8
+ using System . Diagnostics . Contracts ;
8
9
using System . Runtime . CompilerServices ;
9
10
using Microsoft . Collections . Extensions ;
10
11
using Microsoft . Toolkit . Mvvm . Messaging . Internals ;
@@ -181,8 +182,8 @@ public TMessage Send<TMessage, TToken>(TMessage message, TToken token)
181
182
return message ;
182
183
}
183
184
184
- recipients = new ArrayPoolBufferWriter < object > ( ) ;
185
- handlers = new ArrayPoolBufferWriter < object > ( ) ;
185
+ recipients = ArrayPoolBufferWriter < object > . Create ( ) ;
186
+ handlers = ArrayPoolBufferWriter < object > . Create ( ) ;
186
187
187
188
// We need a local, temporary copy of all the pending recipients and handlers to
188
189
// invoke, to avoid issues with handlers unregistering from messages while we're
@@ -232,8 +233,8 @@ public void Cleanup()
232
233
{
233
234
lock ( this . recipientsMap )
234
235
{
235
- using ArrayPoolBufferWriter < Type2 > type2s = new ArrayPoolBufferWriter < Type2 > ( ) ;
236
- using ArrayPoolBufferWriter < object > emptyRecipients = new ArrayPoolBufferWriter < object > ( ) ;
236
+ using ArrayPoolBufferWriter < Type2 > type2s = ArrayPoolBufferWriter < Type2 > . Create ( ) ;
237
+ using ArrayPoolBufferWriter < object > emptyRecipients = ArrayPoolBufferWriter < object > . Create ( ) ;
237
238
238
239
var enumerator = this . recipientsMap . GetEnumerator ( ) ;
239
240
@@ -385,7 +386,12 @@ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
385
386
/// A simple buffer writer implementation using pooled arrays.
386
387
/// </summary>
387
388
/// <typeparam name="T">The type of items to store in the list.</typeparam>
388
- private sealed class ArrayPoolBufferWriter < T > : IDisposable
389
+ /// <remarks>
390
+ /// This type is a <see langword="ref"/> <see langword="struct"/> to avoid the object allocation and to
391
+ /// enable the pattern-based <see cref="IDisposable"/> support. We aren't worried with consumers not
392
+ /// using this type correctly since it's private and only accessible within the parent type.
393
+ /// </remarks>
394
+ private ref struct ArrayPoolBufferWriter < T >
389
395
{
390
396
/// <summary>
391
397
/// The default buffer size to use to expand empty arrays.
@@ -403,12 +409,13 @@ private sealed class ArrayPoolBufferWriter<T> : IDisposable
403
409
private int index ;
404
410
405
411
/// <summary>
406
- /// Initializes a new instance of the <see cref="ArrayPoolBufferWriter{T}"/> class .
412
+ /// Creates a new instance of the <see cref="ArrayPoolBufferWriter{T}"/> struct .
407
413
/// </summary>
408
- public ArrayPoolBufferWriter ( )
414
+ [ Pure ]
415
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
416
+ public static ArrayPoolBufferWriter < T > Create ( )
409
417
{
410
- this . array = ArrayPool < T > . Shared . Rent ( DefaultInitialBufferSize ) ;
411
- this . index = 0 ;
418
+ return new ArrayPoolBufferWriter < T > { array = ArrayPool < T > . Shared . Rent ( DefaultInitialBufferSize ) } ;
412
419
}
413
420
414
421
/// <summary>
@@ -461,7 +468,7 @@ private void ResizeBuffer()
461
468
this . array = rent ;
462
469
}
463
470
464
- /// <inheritdoc/>
471
+ /// <inheritdoc cref="IDisposable.Dispose" />
465
472
public void Dispose ( )
466
473
{
467
474
Array . Clear ( this . array , 0 , this . index ) ;
0 commit comments