@@ -133,16 +133,23 @@ public void Clear()
133
133
_backing = _backing . Clear ( ) ;
134
134
}
135
135
136
+ /// <summary>
137
+ /// Gets an enumerator over all the properties in the collection
138
+ /// Enumeration is in undefined order. This overload exposes the struct enumerator
139
+ /// directly to avoid an allocation due to boxing.
140
+ /// </summary>
141
+ public ImmutableDictionary < string , T > . Enumerator GetEnumerator ( ) => _backing . GetEnumerator ( ) ;
142
+
136
143
/// <summary>
137
144
/// Gets an enumerator over all the properties in the collection
138
145
/// Enumeration is in undefined order
139
146
/// </summary>
140
- public IEnumerator < T > GetEnumerator ( ) => _backing . Values . GetEnumerator ( ) ;
147
+ IEnumerator < T > IEnumerable < T > . GetEnumerator ( ) => new Enumerator ( this ) ;
141
148
142
149
/// <summary>
143
150
/// Get an enumerator over entries
144
151
/// </summary>
145
- IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
152
+ IEnumerator IEnumerable . GetEnumerator ( ) => new Enumerator ( this ) ;
146
153
147
154
#region IEquatable<CopyOnWritePropertyDictionary<T>> Members
148
155
@@ -347,9 +354,24 @@ public void Set(T projectProperty)
347
354
/// <param name="other">An enumerator over the properties to add.</param>
348
355
public void ImportProperties ( IEnumerable < T > other )
349
356
{
350
- _backing = _backing . SetItems ( Items ( ) ) ;
357
+ if ( other is CopyOnWritePropertyDictionary < T > copyOnWriteDictionary )
358
+ {
359
+ _backing = _backing . SetItems ( DictionaryItems ( copyOnWriteDictionary ) ) ;
360
+ }
361
+ else
362
+ {
363
+ _backing = _backing . SetItems ( Items ( other ) ) ;
364
+ }
351
365
352
- IEnumerable < KeyValuePair < string , T > > Items ( )
366
+ static IEnumerable < KeyValuePair < string , T > > DictionaryItems ( CopyOnWritePropertyDictionary < T > copyOnWriteDictionary )
367
+ {
368
+ foreach ( KeyValuePair < string , T > kvp in copyOnWriteDictionary )
369
+ {
370
+ yield return new ( kvp . Value . Key , kvp . Value ) ;
371
+ }
372
+ }
373
+
374
+ static IEnumerable < KeyValuePair < string , T > > Items ( IEnumerable < T > other )
353
375
{
354
376
foreach ( T property in other )
355
377
{
@@ -366,5 +388,38 @@ public ICopyOnWritePropertyDictionary<T> DeepClone()
366
388
{
367
389
return new CopyOnWritePropertyDictionary < T > ( this ) ;
368
390
}
391
+
392
+ /// <summary>
393
+ /// Struct based enumerator to expose the values of the backing collection.
394
+ /// This avoids the allocation when accessing the Values property directly.
395
+ /// </summary>
396
+ public struct Enumerator : IEnumerator < T >
397
+ {
398
+ private ImmutableDictionary < string , T > . Enumerator _dictionaryEnumerator ;
399
+ public Enumerator ( CopyOnWritePropertyDictionary < T > dictionary )
400
+ {
401
+ _dictionaryEnumerator = dictionary . _backing . GetEnumerator ( ) ;
402
+ }
403
+
404
+ public T Current { get ; private set ; }
405
+
406
+ readonly object IEnumerator . Current => Current ;
407
+
408
+ public void Dispose ( ) => _dictionaryEnumerator . Dispose ( ) ;
409
+
410
+ public bool MoveNext ( )
411
+ {
412
+ if ( _dictionaryEnumerator . MoveNext ( ) )
413
+ {
414
+ Current = _dictionaryEnumerator . Current . Value ;
415
+
416
+ return true ;
417
+ }
418
+
419
+ return false ;
420
+ }
421
+
422
+ public void Reset ( ) => _dictionaryEnumerator . Reset ( ) ;
423
+ }
369
424
}
370
425
}
0 commit comments