From 7995334768e9dbafc88e00bb0f26aa477a1b6320 Mon Sep 17 00:00:00 2001 From: Anirudh Agnihotry Date: Wed, 14 Feb 2018 17:47:14 -0800 Subject: [PATCH] StringComparer Create(culture, CompareOptions) overload (#16334) * String Create options overlaod * Minor Change * Feedback * validation on options * obsolete removed * Implementing Iserializable and removing ignorecase * HashCode and serialization changes * made inline * Space Corrected --- src/mscorlib/shared/System/StringComparer.cs | 67 +++++++++++++++++++++------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/src/mscorlib/shared/System/StringComparer.cs b/src/mscorlib/shared/System/StringComparer.cs index 73c0135..b5f20c9 100644 --- a/src/mscorlib/shared/System/StringComparer.cs +++ b/src/mscorlib/shared/System/StringComparer.cs @@ -13,8 +13,8 @@ namespace System [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public abstract class StringComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer { - private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false); - private static readonly CultureAwareComparer s_invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, true); + private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, CompareOptions.None); + private static readonly CultureAwareComparer s_invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, CompareOptions.IgnoreCase); private static readonly OrdinalCaseSensitiveComparer s_ordinal = new OrdinalCaseSensitiveComparer(); private static readonly OrdinalIgnoreCaseComparer s_ordinalIgnoreCase = new OrdinalIgnoreCaseComparer(); @@ -38,7 +38,7 @@ namespace System { get { - return new CultureAwareComparer(CultureInfo.CurrentCulture, false); + return new CultureAwareComparer(CultureInfo.CurrentCulture, CompareOptions.None); } } @@ -46,7 +46,7 @@ namespace System { get { - return new CultureAwareComparer(CultureInfo.CurrentCulture, true); + return new CultureAwareComparer(CultureInfo.CurrentCulture, CompareOptions.IgnoreCase); } } @@ -94,8 +94,18 @@ namespace System { throw new ArgumentNullException(nameof(culture)); } + + return new CultureAwareComparer(culture, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None); + } + + public static StringComparer Create(CultureInfo culture, CompareOptions options) + { + if (culture == null) + { + throw new ArgumentException(nameof(culture)); + } - return new CultureAwareComparer(culture, ignoreCase); + return new CultureAwareComparer(culture, options); } public int Compare(object x, object y) @@ -123,7 +133,6 @@ namespace System throw new ArgumentException(SR.Argument_ImplementIComparable); } - public new bool Equals(Object x, Object y) { if (x == y) return true; @@ -163,32 +172,50 @@ namespace System [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public sealed class CultureAwareComparer : StringComparer + public sealed class CultureAwareComparer : StringComparer, ISerializable { + private const CompareOptions ValidCompareMaskOffFlags = ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort); + private readonly CompareInfo _compareInfo; // Do not rename (binary serialization) - private readonly bool _ignoreCase; // Do not rename (binary serialization) + private CompareOptions _options; - internal CultureAwareComparer(CultureInfo culture, bool ignoreCase) + internal CultureAwareComparer(CultureInfo culture, CompareOptions compareOptions) { _compareInfo = culture.CompareInfo; - _ignoreCase = ignoreCase; + + if ((compareOptions & CultureAwareComparer.ValidCompareMaskOffFlags) != 0) + { + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(compareOptions)); + } + _options = compareOptions; } - private CompareOptions Options => _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None; + private CultureAwareComparer(SerializationInfo info, StreamingContext context) + { + _compareInfo = (CompareInfo)info.GetValue("_compareInfo", typeof(CompareInfo)); + bool ignoreCase = info.GetBoolean("_ignoreCase"); + + var obj = info.GetValueNoThrow("_options", typeof(CompareOptions)); + if (obj != null) + _options = (CompareOptions)obj; + + // fix up the _options value in case we are getting old serialized object not having _options + _options |= ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None; + } public override int Compare(string x, string y) { if (object.ReferenceEquals(x, y)) return 0; if (x == null) return -1; if (y == null) return 1; - return _compareInfo.Compare(x, y, Options); + return _compareInfo.Compare(x, y, _options); } public override bool Equals(string x, string y) { if (object.ReferenceEquals(x, y)) return true; if (x == null || y == null) return false; - return _compareInfo.Compare(x, y, Options) == 0; + return _compareInfo.Compare(x, y, _options) == 0; } public override int GetHashCode(string obj) @@ -197,7 +224,7 @@ namespace System { throw new ArgumentNullException(nameof(obj)); } - return _compareInfo.GetHashCodeOfString(obj, Options); + return _compareInfo.GetHashCodeOfString(obj, _options); } // Equals method for the comparer itself. @@ -206,14 +233,20 @@ namespace System CultureAwareComparer comparer = obj as CultureAwareComparer; return comparer != null && - _ignoreCase == comparer._ignoreCase && + _options == comparer._options && _compareInfo.Equals(comparer._compareInfo); } public override int GetHashCode() { - int hashCode = _compareInfo.GetHashCode(); - return _ignoreCase ? ~hashCode : hashCode; + return _compareInfo.GetHashCode() ^ ((int)_options & 0x7FFFFFFF); + } + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("_compareInfo", _compareInfo); + info.AddValue("_options", _options); + info.AddValue("_ignoreCase", (_options & CompareOptions.IgnoreCase) != 0); } } -- 2.7.4