Split OrdinalIgnoreCaseComparer from OrdinalComparer
authorStephen Toub <stoub@microsoft.com>
Thu, 23 Feb 2017 14:28:30 +0000 (09:28 -0500)
committerStephen Toub <stoub@microsoft.com>
Fri, 24 Feb 2017 03:10:24 +0000 (22:10 -0500)
They're both used very frequently, and we can eliminate the branches on checking _ignoreCase from every operation.

Commit migrated from https://github.com/dotnet/coreclr/commit/a15b54477fb9503d2787b751e2c0b25c12becf37

src/coreclr/src/mscorlib/src/System/StringComparer.cs

index c50a19b..818d629 100644 (file)
@@ -18,8 +18,8 @@ namespace System
     {
         private static readonly StringComparer _invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false);
         private static readonly StringComparer _invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, true);
-        private static readonly StringComparer _ordinal = new OrdinalComparer(false);
-        private static readonly StringComparer _ordinalIgnoreCase = new OrdinalComparer(true);
+        private static readonly StringComparer _ordinal = new OrdinalComparer();
+        private static readonly StringComparer _ordinalIgnoreCase = new OrdinalIgnoreCaseComparer();        
 
         public static StringComparer InvariantCulture
         {
@@ -249,96 +249,77 @@ namespace System
 
     }
 
-    // Provide x more optimal implementation of ordinal comparison.
+    // Provide a more optimal implementation of ordinal comparison.
     [Serializable]
-    internal sealed class OrdinalComparer : StringComparer
-#if FEATURE_RANDOMIZED_STRING_HASHING
+    internal sealed class OrdinalComparer : StringComparer 
+#if FEATURE_RANDOMIZED_STRING_HASHING           
         , IWellKnownStringEqualityComparer
 #endif
     {
-        private bool _ignoreCase;
+        public override int Compare(string x, string y) =>
+            object.ReferenceEquals(x, y) ? 0 :
+            x == null ? -1 :
+            y == null ? 1 :
+            string.CompareOrdinal(x, y);
 
-        internal OrdinalComparer(bool ignoreCase)
-        {
-            _ignoreCase = ignoreCase;
-        }
+        public override bool Equals(string x, string y) =>
+            object.ReferenceEquals(x, y) ||
+            (x != null && x.Equals(y));
 
-        public override int Compare(string x, string y)
+        public override int GetHashCode(string obj)
         {
-            if (Object.ReferenceEquals(x, y)) return 0;
-            if (x == null) return -1;
-            if (y == null) return 1;
-
-            if (_ignoreCase)
+            if (obj == null)
             {
-                return String.Compare(x, y, StringComparison.OrdinalIgnoreCase);
+                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
             }
-
-            return String.CompareOrdinal(x, y);
+            return obj.GetHashCode();
         }
 
-        public override bool Equals(string x, string y)
-        {
-            if (Object.ReferenceEquals(x, y)) return true;
-            if (x == null || y == null) return false;
-
-            if (_ignoreCase)
-            {
-                if (x.Length != y.Length)
-                {
-                    return false;
-                }
-                return (String.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
-            }
-            return x.Equals(y);
-        }
+        // Equals/GetHashCode methods for the comparer itself. 
+        public override bool Equals(Object obj) => obj is OrdinalComparer;
+        public override int GetHashCode() => nameof(OrdinalComparer).GetHashCode();
 
-        public override int GetHashCode(string obj)
-        {
-            if (obj == null)
-            {
-                throw new ArgumentNullException(nameof(obj));
-            }
-            Contract.EndContractBlock();
+#if FEATURE_RANDOMIZED_STRING_HASHING           
+        IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() => this;
+#endif
+    }
 
-            if (_ignoreCase)
-            {
-                return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
-            }
+    // Provide a more optimal implementation of ordinal ignore-case comparison.
+    [Serializable]
+    internal sealed class OrdinalIgnoreCaseComparer : StringComparer
+#if FEATURE_RANDOMIZED_STRING_HASHING
+        , IWellKnownStringEqualityComparer
+#endif
+    {
+        public override int Compare(string x, string y) =>
+            object.ReferenceEquals(x, y) ? 0 :
+            x == null ? -1 :
+            y == null ? 1 :
+            string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
 
-            return obj.GetHashCode();
-        }
+        public override bool Equals(string x, string y) =>
+            object.ReferenceEquals(x, y) ||
+            (x != null && x.Equals(y, StringComparison.OrdinalIgnoreCase));
 
-        // Equals method for the comparer itself. 
-        public override bool Equals(Object obj)
+        public override int GetHashCode(string obj)
         {
-            OrdinalComparer comparer = obj as OrdinalComparer;
-            if (comparer == null)
+            if (obj == null)
             {
-                return false;
+                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
             }
-            return (_ignoreCase == comparer._ignoreCase);
-        }
-
-        public override int GetHashCode()
-        {
-            string name = "OrdinalComparer";
-            int hashCode = name.GetHashCode();
-            return _ignoreCase ? (~hashCode) : hashCode;
+            return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
         }
 
-#if FEATURE_RANDOMIZED_STRING_HASHING           
+        // Equals/GetHashCode methods for the comparer itself. 
+        public override bool Equals(Object obj) => obj is OrdinalIgnoreCaseComparer;
+        public override int GetHashCode() => nameof(OrdinalIgnoreCaseComparer).GetHashCode();
 
-        IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization()
-        {
-            return this;
-        }
+#if FEATURE_RANDOMIZED_STRING_HASHING
+        IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() => this;
 #endif
-
     }
 
 #if FEATURE_RANDOMIZED_STRING_HASHING           
-
     // This interface is implemented by string comparers in the framework that can opt into
     // randomized hashing behaviors. 
     internal interface IWellKnownStringEqualityComparer