using System.Collections.Generic; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols; internal sealed class DelegateCacheContainer : SynthesizedContainer { private sealed class CLRSignatureComparer : IEqualityComparer<(TypeSymbol? constrainedToTypeOpt, TypeSymbol delegateType, MethodSymbol targetMethod)> { public static readonly CLRSignatureComparer Instance = new CLRSignatureComparer(); public bool Equals((TypeSymbol? constrainedToTypeOpt, TypeSymbol delegateType, MethodSymbol targetMethod) x, (TypeSymbol? constrainedToTypeOpt, TypeSymbol delegateType, MethodSymbol targetMethod) y) { EqualityComparer cLRSignature = SymbolEqualityComparer.CLRSignature; if (cLRSignature.Equals(x.delegateType, y.delegateType) && cLRSignature.Equals(x.targetMethod, y.targetMethod)) { return cLRSignature.Equals(x.constrainedToTypeOpt, y.constrainedToTypeOpt); } return false; } public int GetHashCode((TypeSymbol? constrainedToTypeOpt, TypeSymbol delegateType, MethodSymbol targetMethod) conversion) { EqualityComparer cLRSignature = SymbolEqualityComparer.CLRSignature; int num = Hash.Combine(cLRSignature.GetHashCode(conversion.delegateType), cLRSignature.GetHashCode(conversion.targetMethod)); var (typeSymbol, _, _) = conversion; if ((object)typeSymbol != null) { num = Hash.Combine(num, cLRSignature.GetHashCode(typeSymbol)); } return num; } } private readonly Symbol _containingSymbol; private readonly NamedTypeSymbol? _constructedContainer; private readonly Dictionary<(TypeSymbol?, TypeSymbol, MethodSymbol), FieldSymbol> _delegateFields = new Dictionary<(TypeSymbol, TypeSymbol, MethodSymbol), FieldSymbol>(CLRSignatureComparer.Instance); public override Symbol ContainingSymbol => _containingSymbol; public override bool AreLocalsZeroed { get { throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/DelegateCacheContainer.cs", 42); } } public override TypeKind TypeKind => (TypeKind)2; public override bool IsStatic => true; internal override bool IsRecord => false; internal override bool IsRecordStruct => false; internal DelegateCacheContainer(TypeSymbol containingType, int generationOrdinal) : base(GeneratedNames.DelegateCacheContainerType(generationOrdinal), null) { _containingSymbol = containingType; } internal DelegateCacheContainer(MethodSymbol ownerMethod, int topLevelMethodOrdinal, int ownerUniqueId, int generationOrdinal) : base(GeneratedNames.DelegateCacheContainerType(generationOrdinal, ownerMethod.Name, topLevelMethodOrdinal, ownerUniqueId), ownerMethod) { _containingSymbol = ownerMethod.ContainingType; _constructedContainer = Construct(base.ConstructedFromTypeParameters); } internal override bool HasPossibleWellKnownCloneMethod() { return false; } internal FieldSymbol GetOrAddCacheField(SyntheticBoundNodeFactory factory, BoundDelegateCreationExpression boundDelegateCreation) { MethodSymbol methodOpt = boundDelegateCreation.MethodOpt; TypeSymbol type = boundDelegateCreation.Type; TypeSymbol item = (((methodOpt.IsAbstract || methodOpt.IsVirtual) && boundDelegateCreation.Argument is BoundTypeExpression boundTypeExpression) ? boundTypeExpression.Type : null); if (_delegateFields.TryGetValue((item, type, methodOpt), out FieldSymbol value)) { return value; } TypeSymbol type2 = (TypeParameters.IsEmpty ? type : base.TypeMap.SubstituteType(type).Type); string name = GeneratedNames.DelegateCacheContainerFieldName(_delegateFields.Count, methodOpt.Name); value = new SynthesizedFieldSymbol(this, type2, name, isPublic: true, isReadOnly: false, isStatic: true); factory.AddField(this, value); if (!TypeParameters.IsEmpty) { value = value.AsMember(_constructedContainer); } _delegateFields.Add((item, type, methodOpt), value); return value; } }