Files
2026-08-27 10:56:38 -06:00

98 lines
3.8 KiB
C#

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<Symbol> 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<Symbol> 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;
}
}