Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
<Compile Include="$(BclSourcesRoot)\System\Collections\ObjectModel\ReadOnlyDictionary.cs" />
<Compile Include="$(BclSourcesRoot)\System\Currency.cs" />
<Compile Include="$(BclSourcesRoot)\System\DefaultBinder.CanConvert.cs" />
<Compile Include="$(BclSourcesRoot)\System\Delegate.cs" />
<Compile Include="$(BclSourcesRoot)\System\Delegate.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Debugger.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\EditAndContinueHelper.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\NativeRuntimeEventSource.cs" Condition="'$(FeaturePerfTracing)' == 'true'"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Decimal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Decimal.DecCalc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DefaultBinder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Delegate.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\CodeAnalysis\SuppressMessageAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\ConditionalAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Contracts\ContractException.cs" />
Expand Down
126 changes: 126 additions & 0 deletions src/System.Private.CoreLib/shared/System/Delegate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// 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.Reflection;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing license header.

using System.Runtime.CompilerServices;
using System.Runtime.Serialization;

namespace System
{
public abstract partial class Delegate : ICloneable, ISerializable
{
private Delegate()
{
}

public virtual object Clone() => MemberwiseClone();

public static Delegate Combine(Delegate a, Delegate b)
{
if (a is null)
return b;

return a.CombineImpl(b);
}

public static Delegate Combine(params Delegate[] delegates)
{
if (delegates is null || delegates.Length == 0)
return null;

Delegate d = delegates [0];
for (int i = 1; i < delegates.Length; i++)
d = Combine(d, delegates[i]);

return d;
}

protected virtual Delegate CombineImpl(Delegate d) => throw new MulticastNotSupportedException(SR.Multicast_Combine);

// V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed.
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method) => CreateDelegate(type, firstArgument, method, throwOnBindFailure: true);

// V1 api: Creates open delegates to static or instance methods - relaxed signature checking allowed.
public static Delegate CreateDelegate(Type type, MethodInfo method) => CreateDelegate(type, method, throwOnBindFailure: true);

// V1 api: Creates closed delegates to instance methods only, relaxed signature checking disallowed.
public static Delegate CreateDelegate(Type type, object target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true);
public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true);

// V1 api: Creates open delegates to static methods only, relaxed signature checking disallowed.
public static Delegate CreateDelegate(Type type, Type target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true);
public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true);

public object DynamicInvoke(params object[] args)
{
return DynamicInvokeImpl(args);
}

public virtual Delegate[] GetInvocationList() => new Delegate[] { this };

public virtual void GetObjectData(SerializationInfo info, StreamingContext context) => throw new PlatformNotSupportedException();

public MethodInfo Method => GetMethodImpl();

protected virtual Delegate RemoveImpl(Delegate d) => d.Equals(this) ? null : this;

public static Delegate Remove(Delegate source, Delegate value)
{
if (source == null)
return null;

if (value == null)
return source;

if (!InternalEqualTypes(source, value))
throw new ArgumentException(SR.Arg_DlgtTypeMis);

return source.RemoveImpl(value);
}

public static Delegate RemoveAll(Delegate source, Delegate value)
{
Delegate newDelegate = null;

do
{
newDelegate = source;
source = Remove(source, value);
}
while (newDelegate != source);

return newDelegate;
}

// Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Delegate d1, Delegate d2)
{
// Test d2 first to allow branch elimination when inlined for null checks (== null)
// so it can become a simple test
if (d2 is null)
{
// return true/false not the test result https://github.com/dotnet/coreclr/issues/914
return (d1 is null) ? true : false;
}

return ReferenceEquals(d2, d1) || d2.Equals((object)d1);
}

// Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Delegate d1, Delegate d2)
{
// Test d2 first to allow branch elimination when inlined for not null checks (!= null)
// so it can become a simple test
if (d2 is null)
{
// return true/false not the test result https://github.com/dotnet/coreclr/issues/914
return (d1 is null) ? false : true;
}

return ReferenceEquals(d2, d1) ? false : !d2.Equals(d1);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace System
{
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public abstract class Delegate : ICloneable, ISerializable
public abstract partial class Delegate : ICloneable, ISerializable
{
// _target is the object we will invoke on
internal object _target;
Expand Down Expand Up @@ -84,22 +84,6 @@ protected Delegate(Type target, string method)
DelegateBindingFlags.CaselessMatching);
}

// Protect the default constructor so you can't build a delegate
private Delegate()
{
}

public object DynamicInvoke(params object[] args)
{
// Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
// But to maintain backward compatibility we can't switch to calling an
// internal overload of DynamicInvokeImpl that takes a stack mark.
// Fortunately the stack walker skips all the reflection invocation frames including this one.
// So this method will never be returned by the stack walker as the caller.
// See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
return DynamicInvokeImpl(args);
}

protected virtual object DynamicInvokeImpl(object[] args)
{
RuntimeMethodHandleInternal method = new RuntimeMethodHandleInternal(GetInvokeMethod());
Expand Down Expand Up @@ -177,42 +161,6 @@ public override int GetHashCode()
return GetType().GetHashCode();
}

public static Delegate Combine(Delegate a, Delegate b)
{
if ((object)a == null) // cast to object for a more efficient test
return b;

return a.CombineImpl(b);
}

public static Delegate Combine(params Delegate[] delegates)
{
if (delegates == null || delegates.Length == 0)
return null;

Delegate d = delegates[0];
for (int i = 1; i < delegates.Length; i++)
d = Combine(d, delegates[i]);

return d;
}

public virtual Delegate[] GetInvocationList()
{
Delegate[] d = new Delegate[1];
d[0] = this;
return d;
}

// This routine will return the method
public MethodInfo Method
{
get
{
return GetMethodImpl();
}
}

protected virtual MethodInfo GetMethodImpl()
{
if ((_methodBase == null) || !(_methodBase is MethodInfo))
Expand Down Expand Up @@ -276,63 +224,6 @@ public object Target
}
}


public static Delegate Remove(Delegate source, Delegate value)
{
if (source == null)
return null;

if (value == null)
return source;

if (!InternalEqualTypes(source, value))
throw new ArgumentException(SR.Arg_DlgtTypeMis);

return source.RemoveImpl(value);
}

public static Delegate RemoveAll(Delegate source, Delegate value)
{
Delegate newDelegate = null;

do
{
newDelegate = source;
source = Remove(source, value);
}
while (newDelegate != source);

return newDelegate;
}

protected virtual Delegate CombineImpl(Delegate d)
{
throw new MulticastNotSupportedException(SR.Multicast_Combine);
}

protected virtual Delegate RemoveImpl(Delegate d)
{
return (d.Equals(this)) ? null : this;
}


public virtual object Clone()
{
return MemberwiseClone();
}

// V1 API.
public static Delegate CreateDelegate(Type type, object target, string method)
{
return CreateDelegate(type, target, method, false, true);
}

// V1 API.
public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase)
{
return CreateDelegate(type, target, method, ignoreCase, true);
}

// V1 API.
public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
{
Expand Down Expand Up @@ -371,18 +262,6 @@ public static Delegate CreateDelegate(Type type, object target, string method, b
return d;
}

// V1 API.
public static Delegate CreateDelegate(Type type, Type target, string method)
{
return CreateDelegate(type, target, method, false, true);
}

// V1 API.
public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase)
{
return CreateDelegate(type, target, method, ignoreCase, true);
}

// V1 API.
public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
{
Expand Down Expand Up @@ -462,12 +341,6 @@ public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOn
return d;
}

// V2 API.
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method)
{
return CreateDelegate(type, firstArgument, method, true);
}

// V2 API.
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
{
Expand Down Expand Up @@ -505,43 +378,6 @@ public static Delegate CreateDelegate(Type type, object firstArgument, MethodInf
return d;
}

// Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Delegate d1, Delegate d2)
{
// Test d2 first to allow branch elimination when inlined for null checks (== null)
// so it can become a simple test
if (d2 is null)
{
// return true/false not the test result https://github.com/dotnet/coreclr/issues/914
return (d1 is null) ? true : false;
}

return ReferenceEquals(d2, d1) ? true : d2.Equals((object)d1);
}

public static bool operator !=(Delegate d1, Delegate d2)
{
// Test d2 first to allow branch elimination when inlined for not null checks (!= null)
// so it can become a simple test
if (d2 is null)
{
// return true/false not the test result https://github.com/dotnet/coreclr/issues/914
return (d1 is null) ? false : true;
}

return ReferenceEquals(d2, d1) ? false : !d2.Equals(d1);
}

//
// Implementation of ISerializable
//

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new PlatformNotSupportedException();
}

//
// internal implementation details (FCALLS and utilities)
//
Expand Down Expand Up @@ -614,12 +450,6 @@ internal static Delegate CreateDelegateNoSecurityCheck(RuntimeType type, object
return d;
}

// V1 API.
public static Delegate CreateDelegate(Type type, MethodInfo method)
{
return CreateDelegate(type, method, true);
}

internal static Delegate CreateDelegateInternal(RuntimeType rtType, RuntimeMethodInfo rtMethod, object firstArgument, DelegateBindingFlags flags)
{
Delegate d = InternalAlloc(rtType);
Expand Down