diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs index 521000b056cdad..d5727eb2ce13b4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs @@ -172,7 +172,7 @@ internal void StoreDynamicMethod(MethodInfo dynamicMethod) // This method will combine this delegate with the passed delegate // to form a new delegate. - protected sealed override Delegate CombineImpl(Delegate? follow) + internal new Delegate CombineImpl(Delegate? follow) { if (follow is null) return this; @@ -290,21 +290,21 @@ private static bool EqualInvocationLists(object[] a, object[] b, int start, int // look at the invocation list.) If this is found we remove it from // this list and return a new delegate. If its not found a copy of the // current list is returned. - protected sealed override Delegate? RemoveImpl(Delegate value) + internal new Delegate? RemoveImpl(Delegate? value) { // There is a special case were we are removing using a delegate as // the value we need to check for this case // MulticastDelegate? v = value as MulticastDelegate; - if (v == null) return this; + if (v._invocationList is not object[]) { if (_invocationList is not object[] invocationList) { // they are both not real Multicast - if (Equals(value)) + if (Equals(v)) return null; } else @@ -312,7 +312,7 @@ private static bool EqualInvocationLists(object[] a, object[] b, int start, int int invocationCount = (int)_invocationCount; for (int i = invocationCount; --i >= 0;) { - if (value.Equals(invocationList[i])) + if (v.Equals(invocationList[i])) { if (invocationCount == 2) { @@ -362,7 +362,7 @@ private static bool EqualInvocationLists(object[] a, object[] b, int start, int } // This method returns the Invocation list of this multicast delegate. - public sealed override Delegate[] GetInvocationList() + internal new Delegate[] GetInvocationList() { Delegate[] del; if (_invocationList is not object[] invocationList) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs index b59e007cee8d33..0f3d189050dfd6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs @@ -484,7 +484,7 @@ private static bool TrySetSlot(Wrapper[] a, int index, Delegate o) // This method will combine this delegate with the passed delegate // to form a new delegate. - protected virtual Delegate CombineImpl(Delegate? d) + protected Delegate CombineImpl(Delegate? d) { if (d is null) return this; @@ -602,7 +602,7 @@ private static bool EqualInvocationLists(Wrapper[] a, Wrapper[] b, int start, in // look at the invocation list.) If this is found we remove it from // this list and return a new delegate. If its not found a copy of the // current list is returned. - protected virtual Delegate? RemoveImpl(Delegate d) + protected Delegate? RemoveImpl(Delegate? d) { // There is a special case were we are removing using a delegate as // the value we need to check for this case @@ -671,7 +671,7 @@ private static bool EqualInvocationLists(Wrapper[] a, Wrapper[] b, int start, in return this; } - public virtual Delegate[] GetInvocationList() + public Delegate[] GetInvocationList() { if (_helperObject is Wrapper[] invocationList) { diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index ac51112ce4dbd1..a555f6dedb2212 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -2990,9 +2990,6 @@ Resource lookup fell back to the ultimate fallback resources in a satellite assembly, but that satellite either was not found or could not be loaded. Please consider reinstalling or repairing the application. - - Delegates that are not of type MulticastDelegate may not be combined. - An assembly (probably "{1}") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.{0} and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from https://go.microsoft.com/fwlink/?LinkID=169180. \r\nAfter the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL. diff --git a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs index 6efa9f48554fad..0e4c4d28ec5122 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs @@ -68,11 +68,11 @@ public abstract partial class Delegate : ICloneable, ISerializable public static Delegate CreateDelegate(Type type, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.AllMethods)] Type target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!; #if !NATIVEAOT - protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine); + protected Delegate CombineImpl(Delegate? d) => Unsafe.As(this).CombineImpl(d); - protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this; + protected Delegate? RemoveImpl(Delegate? d) => Unsafe.As(this).RemoveImpl(d); - public virtual Delegate[] GetInvocationList() => [this]; + public Delegate[] GetInvocationList() => Unsafe.As(this).GetInvocationList(); /// /// Gets a value that indicates whether the has a single invocation target. diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a5cfe887a4bc94..7e7ae5dbe9f49b 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -2342,7 +2342,7 @@ protected Delegate([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAt public static System.Delegate? Combine(System.Delegate? a, System.Delegate? b) { throw null; } public static System.Delegate? Combine(params System.Delegate?[]? delegates) { throw null; } public static System.Delegate? Combine(params System.ReadOnlySpan delegates) { throw null; } - protected virtual System.Delegate CombineImpl(System.Delegate? d) { throw null; } + protected System.Delegate CombineImpl(System.Delegate? d) { throw null; } public static System.Delegate CreateDelegate(System.Type type, object? firstArgument, System.Reflection.MethodInfo method) { throw null; } public static System.Delegate? CreateDelegate(System.Type type, object? firstArgument, System.Reflection.MethodInfo method, bool throwOnBindFailure) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The target method might be removed")] @@ -2361,7 +2361,7 @@ protected Delegate([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAt public static System.Delegate.InvocationListEnumerator EnumerateInvocationList(TDelegate? d) where TDelegate : System.Delegate { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } - public virtual System.Delegate[] GetInvocationList() { throw null; } + public System.Delegate[] GetInvocationList() { throw null; } protected virtual System.Reflection.MethodInfo GetMethodImpl() { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] @@ -2370,7 +2370,7 @@ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo public static bool operator !=(System.Delegate? d1, System.Delegate? d2) { throw null; } public static System.Delegate? Remove(System.Delegate? source, System.Delegate? value) { throw null; } public static System.Delegate? RemoveAll(System.Delegate? source, System.Delegate? value) { throw null; } - protected virtual System.Delegate? RemoveImpl(System.Delegate d) { throw null; } + protected System.Delegate? RemoveImpl(System.Delegate? d) { throw null; } public partial struct InvocationListEnumerator where TDelegate : System.Delegate { public TDelegate Current { get { throw null; } } @@ -4793,17 +4793,14 @@ public abstract partial class MulticastDelegate : System.Delegate [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The target method might be removed")] protected MulticastDelegate(object target, string method) : base (default(object), default(string)) { } protected MulticastDelegate([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.AllMethods)] System.Type target, string method) : base (default(object), default(string)) { } - protected sealed override System.Delegate CombineImpl(System.Delegate? follow) { throw null; } public sealed override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public sealed override int GetHashCode() { throw null; } - public sealed override System.Delegate[] GetInvocationList() { throw null; } protected override System.Reflection.MethodInfo GetMethodImpl() { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public static bool operator ==(System.MulticastDelegate? d1, System.MulticastDelegate? d2) { throw null; } public static bool operator !=(System.MulticastDelegate? d1, System.MulticastDelegate? d2) { throw null; } - protected sealed override System.Delegate? RemoveImpl(System.Delegate value) { throw null; } } public sealed partial class MulticastNotSupportedException : System.SystemException { diff --git a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml index 95960d00eda311..065f3eff037105 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml @@ -337,6 +337,60 @@ net10.0/System.Runtime.Intrinsics.dll net11.0/System.Runtime.Intrinsics.dll + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + net10.0/mscorlib.dll + net11.0/mscorlib.dll + + + CP0012 + M:System.Delegate.GetInvocationList + net10.0/mscorlib.dll + net11.0/mscorlib.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + net10.0/mscorlib.dll + net11.0/mscorlib.dll + + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + net10.0/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.GetInvocationList + net10.0/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + net10.0/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + net10.0/System.Runtime.dll + net11.0/System.Runtime.dll + + + CP0012 + M:System.Delegate.GetInvocationList + net10.0/System.Runtime.dll + net11.0/System.Runtime.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + net10.0/System.Runtime.dll + net11.0/System.Runtime.dll + CP0014 M:System.Security.Cryptography.X509Certificates.PublicKey.#ctor(System.Security.Cryptography.MLDsa):[T:System.Diagnostics.CodeAnalysis.ExperimentalAttribute] diff --git a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml index 8d18b718a612ae..e33c2d47f78f67 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml @@ -1,4 +1,4 @@ - + @@ -229,6 +229,60 @@ netstandard2.0/System.Xml.dll net11.0/System.Xml.dll + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + netstandard2.0/mscorlib.dll + net11.0/mscorlib.dll + + + CP0012 + M:System.Delegate.GetInvocationList + netstandard2.0/mscorlib.dll + net11.0/mscorlib.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + netstandard2.0/mscorlib.dll + net11.0/mscorlib.dll + + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + netstandard2.0/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.GetInvocationList + netstandard2.0/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + netstandard2.0/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + netstandard2.0/System.Runtime.dll + net11.0/System.Runtime.dll + + + CP0012 + M:System.Delegate.GetInvocationList + netstandard2.0/System.Runtime.dll + net11.0/System.Runtime.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + netstandard2.0/System.Runtime.dll + net11.0/System.Runtime.dll + CP0014 M:System.Collections.IEnumerable.GetEnumerator:[T:System.Runtime.InteropServices.DispIdAttribute] diff --git a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml index a11fe6cb50a601..3c2c66c349e466 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml @@ -1,6 +1,24 @@ - + + + CP0012 + M:System.Delegate.CombineImpl(System.Delegate) + netstandard2.1/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.GetInvocationList + netstandard2.1/netstandard.dll + net11.0/netstandard.dll + + + CP0012 + M:System.Delegate.RemoveImpl(System.Delegate) + netstandard2.1/netstandard.dll + net11.0/netstandard.dll + CP0014 E:System.Diagnostics.Process.ErrorDataReceived:[T:System.ComponentModel.BrowsableAttribute] @@ -853,6 +871,12 @@ netstandard2.1/netstandard.dll net11.0/netstandard.dll + + CP0015 + T:System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute:[T:System.AttributeUsageAttribute] + netstandard2.1/netstandard.dll + net11.0/netstandard.dll + CP0015 T:System.Runtime.CompilerServices.AsyncMethodBuilderAttribute:[T:System.AttributeUsageAttribute] @@ -1003,10 +1027,4 @@ netstandard2.1/netstandard.dll net11.0/netstandard.dll - - CP0015 - T:System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute:[T:System.AttributeUsageAttribute] - netstandard2.1/netstandard.dll - net11.0/netstandard.dll - \ No newline at end of file diff --git a/src/mono/System.Private.CoreLib/src/System/MulticastDelegate.Mono.cs b/src/mono/System.Private.CoreLib/src/System/MulticastDelegate.Mono.cs index 47fb79aa3cdfa7..c026cf46a88539 100644 --- a/src/mono/System.Private.CoreLib/src/System/MulticastDelegate.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/MulticastDelegate.Mono.cs @@ -94,7 +94,7 @@ protected override MethodInfo GetMethodImpl() // Return, in order of invocation, the invocation list // of a MulticastDelegate // - public sealed override Delegate[] GetInvocationList() + internal new Delegate[] GetInvocationList() { if (delegates != null) return (Delegate[])delegates.Clone(); @@ -126,7 +126,7 @@ public sealed override Delegate[] GetInvocationList() // thing should have better been a simple System.Delegate class. // Compiler generated delegates are always MulticastDelegates. // - protected sealed override Delegate CombineImpl(Delegate? follow) + internal new Delegate CombineImpl(Delegate? follow) { if (follow == null) return this; @@ -197,7 +197,7 @@ private static int LastIndexOf(Delegate[] haystack, Delegate[] needle) return -1; } - protected sealed override Delegate? RemoveImpl(Delegate value) + internal new Delegate? RemoveImpl(Delegate? value) { if (value == null) return this;