@@ -53,7 +53,6 @@ internal class RetrievableEntryHashSet<T> : ICollection<T>,
5353 private int _count ;
5454 private int _freeList ;
5555 private int _freeCount ;
56- private int _version ;
5756 private IEqualityComparer < string > _comparer ;
5857 private bool _readOnly ;
5958
@@ -416,7 +415,7 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte
416415 throw new ArgumentNullException ( nameof ( info ) ) ;
417416 }
418417
419- info . AddValue ( VersionName , _version ) ; // need to serialize version to avoid problems with serializing while enumerating
418+ info . AddValue ( VersionName , 0 ) ; // serialize dummy version
420419 info . AddValue ( ComparerName , _comparer , typeof ( IEqualityComparer < string > ) ) ;
421420 info . AddValue ( CapacityName , _buckets == null ? 0 : _buckets . Length ) ;
422421
@@ -464,7 +463,7 @@ public virtual void OnDeserialization(object sender)
464463 _buckets = null ;
465464 }
466465
467- _version = siInfo . GetInt32 ( VersionName ) ;
466+ _ = siInfo . GetInt32 ( VersionName ) ;
468467 _ = HashHelpers . SerializationInfoTable . Remove ( this ) ;
469468 }
470469
@@ -541,7 +540,6 @@ public void TrimExcess()
541540 }
542541
543542 int oldCount = _count ;
544- _version ++ ;
545543 Initialize ( newSize ) ;
546544 Entry [ ] entries = _entries ;
547545 int count = 0 ;
@@ -636,7 +634,6 @@ public void AddOrReplace(T value)
636634 entry . Next = bucket - 1 ; // Value in _buckets is 1-based
637635 entry . Value = value ;
638636 bucket = index + 1 ;
639- _version ++ ;
640637 }
641638
642639 return ;
@@ -737,7 +734,7 @@ public struct Enumerator : IEnumerator<T>
737734 internal Enumerator ( RetrievableEntryHashSet < T > hashSet )
738735 {
739736 _hashSet = hashSet ;
740- _version = hashSet . _version ;
737+ _version = GetVersion ( ) ;
741738 _index = 0 ;
742739 Current = default ;
743740 }
@@ -759,7 +756,7 @@ object IEnumerator.Current
759756
760757 public bool MoveNext ( )
761758 {
762- if ( _version != _hashSet . _version )
759+ if ( _version != GetVersion ( ) )
763760 {
764761 throw new InvalidOperationException ( ) ;
765762 }
@@ -785,14 +782,24 @@ public void Dispose() { }
785782
786783 void IEnumerator . Reset ( )
787784 {
788- if ( _version != _hashSet . _version )
785+ if ( _version != GetVersion ( ) )
789786 {
790787 throw new InvalidOperationException ( ) ;
791788 }
792789
793790 _index = 0 ;
794791 Current = default ;
795792 }
793+
794+ private int GetVersion ( )
795+ {
796+ // As a check on concurrent modifications, check that neither count
797+ // nor freeCount change during enumeration. TrimExcess would change only
798+ // the latter.
799+ // This avoids storing a version field on every collection object, while
800+ // catching almost as many cases.
801+ return _hashSet . _count + _hashSet . _freeCount << 16 ;
802+ }
796803 }
797804 }
798805}
0 commit comments