File: Symbols\AnonymousTypes\PublicSymbols\AnonymousType.DelegatePublicSymbol.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal sealed partial class AnonymousTypeManager
    {
        internal sealed class AnonymousDelegatePublicSymbol : AnonymousTypeOrDelegatePublicSymbol
        {
            private ImmutableArray<Symbol> _lazyMembers;
 
            internal AnonymousDelegatePublicSymbol(AnonymousTypeManager manager, AnonymousTypeDescriptor typeDescr) :
                base(manager, typeDescr)
            {
            }
 
            internal override NamedTypeSymbol MapToImplementationSymbol()
            {
                return Manager.ConstructAnonymousDelegateImplementationSymbol(this, generation: 0);
            }
 
            internal override AnonymousTypeOrDelegatePublicSymbol SubstituteTypes(AbstractTypeMap map)
            {
                var typeDescr = TypeDescriptor.SubstituteTypes(map, out bool changed);
                return changed ?
                    new AnonymousDelegatePublicSymbol(Manager, typeDescr) :
                    this;
            }
 
            public override TypeKind TypeKind => TypeKind.Delegate;
 
            internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => Manager.System_MulticastDelegate;
 
            public override IEnumerable<string> MemberNames => GetMembers().SelectAsArray(member => member.Name);
 
            public override ImmutableArray<Symbol> GetMembers()
            {
                if (_lazyMembers.IsDefault)
                {
                    ImmutableInterlocked.InterlockedInitialize(ref _lazyMembers, CreateMembers());
                }
                return _lazyMembers;
            }
 
            private ImmutableArray<Symbol> CreateMembers()
            {
                var constructor = new SynthesizedDelegateConstructor(this, Manager.System_Object, Manager.System_IntPtr);
                var fields = TypeDescriptor.Fields;
                int parameterCount = fields.Length - 1;
                var parameters = ArrayBuilder<SynthesizedDelegateInvokeMethod.ParameterDescription>.GetInstance(parameterCount);
                for (int i = 0; i < parameterCount; i++)
                {
                    var field = fields[i];
                    parameters.Add(
                        new SynthesizedDelegateInvokeMethod.ParameterDescription(field.TypeWithAnnotations, field.RefKind, field.Scope, field.DefaultValue, isParams: field.IsParams, hasUnscopedRefAttribute: field.HasUnscopedRefAttribute));
                }
                var returnField = fields.Last();
                var invokeMethod = new SynthesizedDelegateInvokeMethod(this, parameters, returnField.TypeWithAnnotations, returnField.RefKind);
                parameters.Free();
                // https://github.com/dotnet/roslyn/issues/56808: Synthesized delegates should include BeginInvoke() and EndInvoke().
                return ImmutableArray.Create<Symbol>(constructor, invokeMethod);
            }
 
            public override ImmutableArray<Symbol> GetMembers(string name) => GetMembers().WhereAsArray((member, name) => member.Name == name, name);
 
            public override bool IsImplicitlyDeclared => true;
 
            public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => ImmutableArray<SyntaxReference>.Empty;
 
            internal override bool Equals(TypeSymbol t2, TypeCompareKind comparison)
            {
                if (ReferenceEquals(this, t2))
                {
                    return true;
                }
 
                var other = t2 as AnonymousDelegatePublicSymbol;
                return other is { } && this.TypeDescriptor.Equals(other.TypeDescriptor, comparison);
            }
 
            public override int GetHashCode()
            {
                return this.TypeDescriptor.GetHashCode();
            }
        }
    }
}