File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\SymbolKey\SymbolKey.SymbolKeyComparer.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
 
namespace Microsoft.CodeAnalysis;
 
internal partial struct SymbolKey
{
    private sealed class SymbolKeyComparer : IEqualityComparer<SymbolKey>
    {
        private readonly ComparisonOptions _options;
 
        private SymbolKeyComparer(ComparisonOptions options)
            => _options = options;
 
        public bool Equals(SymbolKey x, SymbolKey y)
        {
            if (!_options.IgnoreAssemblyKey)
            {
                // Easiest case.  We can directly compare the raw contents of the keys.
                return x.Equals(y, _options.IgnoreCase);
            }
            else
            {
                // This is harder.  To compare these we need to remove the entries related to assemblies.
                //
                // Note: this will remove the language-string as well, so we don't have to worry about that here.
                var data1 = RemoveAssemblyKeys(x._symbolKeyData);
                var data2 = RemoveAssemblyKeys(y._symbolKeyData);
 
                var comparer = _options.IgnoreCase
                    ? StringComparer.OrdinalIgnoreCase
                    : StringComparer.Ordinal;
 
                return comparer.Equals(data1, data2);
            }
        }
 
        private static string RemoveAssemblyKeys(string data)
        {
            var reader = new RemoveAssemblySymbolKeysReader();
            reader.Initialize(data);
            return reader.RemoveAssemblySymbolKeys();
        }
 
        public int GetHashCode(SymbolKey obj)
            => obj.GetHashCode();
 
        public static IEqualityComparer<SymbolKey> GetComparer(bool ignoreCase, bool ignoreAssemblyKey)
            => GetComparer(new ComparisonOptions(ignoreCase, ignoreAssemblyKey));
 
        private static readonly SymbolKeyComparer[] s_cachedComparers = new SymbolKeyComparer[4];
 
        private static SymbolKeyComparer EnsureInitialized(ref SymbolKeyComparer location, ComparisonOptions options)
        {
            // This doesn't need to be interlocked since comparers store no state
            return location ??= new SymbolKeyComparer(options);
        }
 
        public static IEqualityComparer<SymbolKey> GetComparer(ComparisonOptions options)
            => EnsureInitialized(ref s_cachedComparers[options.FlagsValue], options);
    }
}