summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Moseley <danmose@microsoft.com>2019-04-01 13:53:01 -0700
committerGitHub <noreply@github.com>2019-04-01 13:53:01 -0700
commitaebc5acdb6017676255913ba341ee9ff71f2f3ec (patch)
tree2e5282d1009f25beb9d9133744101faa7ba6899b
parentd37dad3721de6cbb30424beb24383305cedfff9c (diff)
downloadcoreclr-aebc5acdb6017676255913ba341ee9ff71f2f3ec.tar.gz
coreclr-aebc5acdb6017676255913ba341ee9ff71f2f3ec.tar.bz2
coreclr-aebc5acdb6017676255913ba341ee9ff71f2f3ec.zip
Nullable annotations for Delegate/MulticastDelegate (#23615)
* Nullable annotations for Delegate/MulticastDelegate * Dead string * Remove TODO's * Review * Review2 * More * More * Unnecessary ? * Update src/System.Private.CoreLib/src/System/MulticastDelegate.cs Co-Authored-By: danmosemsft <danmose@microsoft.com> * Santi feedback * Jan feedback * No assert msg
-rw-r--r--src/System.Private.CoreLib/Resources/Strings.resx3
-rw-r--r--src/System.Private.CoreLib/src/System/Delegate.cs155
-rw-r--r--src/System.Private.CoreLib/src/System/MulticastDelegate.cs64
3 files changed, 92 insertions, 130 deletions
diff --git a/src/System.Private.CoreLib/Resources/Strings.resx b/src/System.Private.CoreLib/Resources/Strings.resx
index a912b83d50..077c47662e 100644
--- a/src/System.Private.CoreLib/Resources/Strings.resx
+++ b/src/System.Private.CoreLib/Resources/Strings.resx
@@ -2944,9 +2944,6 @@
<data name="NotSupported_DelegateMarshalToWrongDomain" xml:space="preserve">
<value>Delegates cannot be marshaled from native code into a domain other than their home domain.</value>
</data>
- <data name="NotSupported_DelegateSerHolderSerial" xml:space="preserve">
- <value>DelegateSerializationHolder objects are designed to represent a delegate during serialization and are not serializable themselves.</value>
- </data>
<data name="NotSupported_DynamicAssembly" xml:space="preserve">
<value>The invoked member is not supported in a dynamic assembly.</value>
</data>
diff --git a/src/System.Private.CoreLib/src/System/Delegate.cs b/src/System.Private.CoreLib/src/System/Delegate.cs
index df9bac4766..20d934cd5c 100644
--- a/src/System.Private.CoreLib/src/System/Delegate.cs
+++ b/src/System.Private.CoreLib/src/System/Delegate.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#nullable enable
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -15,11 +16,11 @@ namespace System
public abstract class Delegate : ICloneable, ISerializable
{
// _target is the object we will invoke on
- internal object _target;
+ internal object? _target; // Initialized by VM as needed; null if static delegate
// MethodBase, either cached after first request or assigned from a DynamicMethod
// For open delegates to collectible types, this may be a LoaderAllocator object
- internal object _methodBase;
+ internal object _methodBase = null!; // Initialized by VM as needed
// _methodPtr is a pointer to the method we will invoke
// It could be a small thunk if this is a static or UM call
@@ -53,7 +54,7 @@ namespace System
throw new ArgumentException(SR.Arg_DlgtTargMeth);
}
- // This constructor is called from a class to generate a
+ // This constructor is called from a class to generate a
// delegate based upon a static method name and the Type object
// for the class defining the method.
protected Delegate(Type target, string method)
@@ -67,8 +68,7 @@ namespace System
if (method == null)
throw new ArgumentNullException(nameof(method));
- RuntimeType rtTarget = target as RuntimeType;
- if (rtTarget == null)
+ if (!(target is RuntimeType rtTarget))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(target));
// This API existed in v1/v1.1 and only expected to create open
@@ -89,10 +89,10 @@ namespace System
{
}
- public object DynamicInvoke(params object[] args)
+ 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
+ // 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.
@@ -100,7 +100,7 @@ namespace System
return DynamicInvokeImpl(args);
}
- protected virtual object DynamicInvokeImpl(object[] args)
+ protected virtual object? DynamicInvokeImpl(object?[]? args)
{
RuntimeMethodHandleInternal method = new RuntimeMethodHandleInternal(GetInvokeMethod());
RuntimeMethodInfo invoke = (RuntimeMethodInfo)RuntimeType.GetMethodBase((RuntimeType)this.GetType(), method);
@@ -109,7 +109,7 @@ namespace System
}
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
if (obj == null || !InternalEqualTypes(this, obj))
return false;
@@ -123,7 +123,7 @@ namespace System
// even though the fields were not all equals the delegates may still match
// When target carries the delegate itself the 2 targets (delegates) may be different instances
// but the delegates are logically the same
- // It may also happen that the method pointer was not jitted when creating one delegate and jitted in the other
+ // It may also happen that the method pointer was not jitted when creating one delegate and jitted in the other
// if that's the case the delegates may still be equals but we need to make a more complicated check
if (_methodPtrAux == IntPtr.Zero)
@@ -152,7 +152,7 @@ namespace System
}
// method ptrs don't match, go down long path
- //
+ //
if (_methodBase == null || d._methodBase == null || !(_methodBase is MethodInfo) || !(d._methodBase is MethodInfo))
return Delegate.InternalEqualMethodHandles(this, d);
else
@@ -177,20 +177,20 @@ namespace System
return GetType().GetHashCode();
}
- public static Delegate Combine(Delegate a, Delegate b)
+ public static Delegate? Combine(Delegate? a, Delegate? b)
{
- if ((object)a == null) // cast to object for a more efficient test
+ if (a is null)
return b;
return a.CombineImpl(b);
}
- public static Delegate Combine(params Delegate[] delegates)
+ public static Delegate? Combine(params Delegate?[]? delegates)
{
if (delegates == null || delegates.Length == 0)
return null;
- Delegate d = delegates[0];
+ Delegate? d = delegates[0];
for (int i = 1; i < delegates.Length; i++)
d = Combine(d, delegates[i]);
@@ -218,7 +218,7 @@ namespace System
if ((_methodBase == null) || !(_methodBase is MethodInfo))
{
IRuntimeMethodInfo method = FindMethodHandle();
- RuntimeType declaringType = RuntimeMethodHandle.GetDeclaringType(method);
+ RuntimeType? declaringType = RuntimeMethodHandle.GetDeclaringType(method);
// need a proper declaring type instance method on a generic type
if (RuntimeTypeHandle.IsGenericTypeDefinition(declaringType) || RuntimeTypeHandle.HasInstantiation(declaringType))
{
@@ -237,7 +237,7 @@ namespace System
// types at each step) until we find the declaring type. Since the declaring type
// we get from the method is probably shared and those in the hierarchy we're
// walking won't be we compare using the generic type definition forms instead.
- Type currentType = _target.GetType();
+ Type currentType = _target!.GetType();
Type targetType = declaringType.GetGenericTypeDefinition();
while (currentType != null)
{
@@ -268,7 +268,7 @@ namespace System
return (MethodInfo)_methodBase;
}
- public object Target
+ public object? Target
{
get
{
@@ -277,7 +277,7 @@ namespace System
}
- public static Delegate Remove(Delegate source, Delegate value)
+ public static Delegate? Remove(Delegate? source, Delegate? value)
{
if (source == null)
return null;
@@ -291,9 +291,9 @@ namespace System
return source.RemoveImpl(value);
}
- public static Delegate RemoveAll(Delegate source, Delegate value)
+ public static Delegate? RemoveAll(Delegate? source, Delegate? value)
{
- Delegate newDelegate = null;
+ Delegate? newDelegate = null;
do
{
@@ -305,12 +305,12 @@ namespace System
return newDelegate;
}
- protected virtual Delegate CombineImpl(Delegate d)
+ protected virtual Delegate CombineImpl(Delegate? d)
{
throw new MulticastNotSupportedException(SR.Multicast_Combine);
}
- protected virtual Delegate RemoveImpl(Delegate d)
+ protected virtual Delegate? RemoveImpl(Delegate d)
{
return (d.Equals(this)) ? null : this;
}
@@ -324,17 +324,17 @@ namespace System
// V1 API.
public static Delegate CreateDelegate(Type type, object target, string method)
{
- return CreateDelegate(type, target, method, false, true);
+ return CreateDelegate(type, target, method, false, throwOnBindFailure: true)!; // Cannot return null because it would have thrown
}
// V1 API.
public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase)
{
- return CreateDelegate(type, target, method, ignoreCase, true);
+ return CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!; // Cannot return null because it would have thrown
}
// V1 API.
- public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
+ public static Delegate? CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
@@ -343,8 +343,7 @@ namespace System
if (method == null)
throw new ArgumentNullException(nameof(method));
- RuntimeType rtType = type as RuntimeType;
- if (rtType == null)
+ if (!(type is RuntimeType rtType))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
if (!rtType.IsDelegate())
throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(type));
@@ -365,7 +364,8 @@ namespace System
{
if (throwOnBindFailure)
throw new ArgumentException(SR.Arg_DlgtTargMeth);
- d = null;
+
+ return null;
}
return d;
@@ -374,17 +374,17 @@ namespace System
// V1 API.
public static Delegate CreateDelegate(Type type, Type target, string method)
{
- return CreateDelegate(type, target, method, false, true);
+ return CreateDelegate(type, target, method, false, throwOnBindFailure: true)!; // Cannot return null because it would have thrown
}
// V1 API.
public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase)
{
- return CreateDelegate(type, target, method, ignoreCase, true);
+ return CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!; // Cannot return null because it would have thrown
}
// V1 API.
- public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
+ public static Delegate? CreateDelegate(Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
@@ -395,12 +395,11 @@ namespace System
if (method == null)
throw new ArgumentNullException(nameof(method));
- RuntimeType rtType = type as RuntimeType;
- RuntimeType rtTarget = target as RuntimeType;
- if (rtType == null)
+ if (!(type is RuntimeType rtType))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
- if (rtTarget == null)
+ if (!(target is RuntimeType rtTarget))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(target));
+
if (!rtType.IsDelegate())
throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(type));
@@ -416,14 +415,15 @@ namespace System
{
if (throwOnBindFailure)
throw new ArgumentException(SR.Arg_DlgtTargMeth);
- d = null;
+
+ return null;
}
return d;
}
// V1 API.
- public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure)
+ public static Delegate? CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure)
{
// Validate the parameters.
if (type == null)
@@ -431,12 +431,10 @@ namespace System
if (method == null)
throw new ArgumentNullException(nameof(method));
- RuntimeType rtType = type as RuntimeType;
- if (rtType == null)
+ if (!(type is RuntimeType rtType))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
- RuntimeMethodInfo rmi = method as RuntimeMethodInfo;
- if (rmi == null)
+ if (!(method is RuntimeMethodInfo rmi))
throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, nameof(method));
if (!rtType.IsDelegate())
@@ -450,7 +448,7 @@ namespace System
// pass us a static method or a method with a non-exact signature
// and the only change in behavior from v1.1 there is that we won't
// fail the call).
- Delegate d = CreateDelegateInternal(
+ Delegate? d = CreateDelegateInternal(
rtType,
rmi,
null,
@@ -463,13 +461,13 @@ namespace System
}
// V2 API.
- public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method)
+ public static Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method)
{
- return CreateDelegate(type, firstArgument, method, true);
+ return CreateDelegate(type, firstArgument, method, throwOnBindFailure: true)!; // Cannot return null because it would have thrown
}
// V2 API.
- public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
+ public static Delegate? CreateDelegate(Type type, object? firstArgument, MethodInfo method, bool throwOnBindFailure)
{
// Validate the parameters.
if (type == null)
@@ -477,12 +475,10 @@ namespace System
if (method == null)
throw new ArgumentNullException(nameof(method));
- RuntimeType rtType = type as RuntimeType;
- if (rtType == null)
+ if (!(type is RuntimeType rtType))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
- RuntimeMethodInfo rmi = method as RuntimeMethodInfo;
- if (rmi == null)
+ if (!(method is RuntimeMethodInfo rmi))
throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, nameof(method));
if (!rtType.IsDelegate())
@@ -493,7 +489,7 @@ namespace System
// instance methods with relaxed signature checking. The delegate
// can also be closed over null. There's no ambiguity with all these
// options since the caller is providing us a specific MethodInfo.
- Delegate d = CreateDelegateInternal(
+ Delegate? d = CreateDelegateInternal(
rtType,
rmi,
firstArgument,
@@ -507,7 +503,7 @@ namespace System
// 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)
+ 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
@@ -517,10 +513,10 @@ namespace System
return (d1 is null) ? true : false;
}
- return ReferenceEquals(d2, d1) ? true : d2.Equals((object)d1);
+ return ReferenceEquals(d2, d1) ? true : d2.Equals((object?)d1);
}
- public static bool operator !=(Delegate d1, Delegate d2)
+ 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
@@ -547,8 +543,7 @@ namespace System
//
// V2 internal API.
- // This is Critical because it skips the security check when creating the delegate.
- internal static Delegate CreateDelegateNoSecurityCheck(Type type, object target, RuntimeMethodHandle method)
+ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target, RuntimeMethodHandle method)
{
// Validate the parameters.
if (type == null)
@@ -557,8 +552,7 @@ namespace System
if (method.IsNullHandle())
throw new ArgumentNullException(nameof(method));
- RuntimeType rtType = type as RuntimeType;
- if (rtType == null)
+ if (!(type is RuntimeType rtType))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
if (!rtType.IsDelegate())
@@ -579,48 +573,13 @@ namespace System
return d;
}
- // Caution: this method is intended for deserialization only, no security checks are performed.
- internal static Delegate CreateDelegateNoSecurityCheck(RuntimeType type, object firstArgument, MethodInfo method)
- {
- // Validate the parameters.
- if (type == null)
- throw new ArgumentNullException(nameof(type));
- if (method == null)
- throw new ArgumentNullException(nameof(method));
-
-
- RuntimeMethodInfo rtMethod = method as RuntimeMethodInfo;
- if (rtMethod == null)
- throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, nameof(method));
-
- if (!type.IsDelegate())
- throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(type));
-
- // This API is used by the formatters when deserializing a delegate.
- // They pass us the specific target method (that was already the
- // target in a valid delegate) so we should bind with the most
- // relaxed rules available (the result will never be ambiguous, it
- // just increases the chance of success with minor (compatible)
- // signature changes). We explicitly skip security checks here --
- // we're not really constructing a delegate, we're cloning an
- // existing instance which already passed its checks.
- Delegate d = CreateDelegateInternal(type, rtMethod, firstArgument,
- DelegateBindingFlags.SkipSecurityChecks |
- DelegateBindingFlags.RelaxedSignature);
-
- if (d == null)
- throw new ArgumentException(SR.Arg_DlgtTargMeth);
-
- return d;
- }
-
// V1 API.
- public static Delegate CreateDelegate(Type type, MethodInfo method)
+ 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)
+ internal static Delegate? CreateDelegateInternal(RuntimeType rtType, RuntimeMethodInfo rtMethod, object? firstArgument, DelegateBindingFlags flags)
{
Delegate d = InternalAlloc(rtType);
@@ -635,10 +594,10 @@ namespace System
//
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern bool BindToMethodName(object target, RuntimeType methodType, string method, DelegateBindingFlags flags);
+ private extern bool BindToMethodName(object? target, RuntimeType methodType, string method, DelegateBindingFlags flags);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern bool BindToMethodInfo(object target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags);
+ private extern bool BindToMethodInfo(object? target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern MulticastDelegate InternalAlloc(RuntimeType type);
@@ -672,7 +631,7 @@ namespace System
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern IntPtr GetCallStub(IntPtr methodPtr);
- internal virtual object GetTarget()
+ internal virtual object? GetTarget()
{
return (_methodPtrAux == IntPtr.Zero) ? _target : null;
}
diff --git a/src/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
index 40f9478c64..e50d42e69d 100644
--- a/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
+++ b/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#nullable enable
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -20,7 +21,7 @@ namespace System
// 1. Multicast delegate
// 2. Secure/Wrapper delegate
// 3. Inner delegate of secure delegate where the secure delegate security context is a collectible method
- private object _invocationList;
+ private object? _invocationList; // Initialized by VM as needed
private IntPtr _invocationCount;
// This constructor is called from the class generated by the
@@ -54,7 +55,7 @@ namespace System
// equals returns true IIF the delegate is not null and has the
// same target, method and invocation list as this object
- public override sealed bool Equals(object obj)
+ public override sealed bool Equals(object? obj)
{
if (obj == null)
return false;
@@ -96,10 +97,10 @@ namespace System
}
else
{
- if ((_invocationList as Delegate) != null)
+ if (_invocationList is Delegate invocationListDelegate)
{
// this is a secure/wrapper delegate so we need to unwrap and check the inner one
- return _invocationList.Equals(obj);
+ return invocationListDelegate.Equals(obj);
}
else
{
@@ -116,7 +117,7 @@ namespace System
// and call the base.Equals()
if (!InvocationListLogicallyNull())
{
- if (!_invocationList.Equals(d._invocationList))
+ if (!_invocationList!.Equals(d._invocationList))
return false;
return base.Equals(d);
}
@@ -134,25 +135,29 @@ namespace System
// Recursive function which will check for equality of the invocation list.
private bool InvocationListEquals(MulticastDelegate d)
{
- Debug.Assert(d != null && (_invocationList as object[]) != null, "bogus delegate in multicast list comparison");
- object[] invocationList = _invocationList as object[];
+ Debug.Assert(d != null);
+ Debug.Assert(_invocationList is object[]);
+ object[] invocationList = (object[])_invocationList;
+
if (d._invocationCount != _invocationCount)
return false;
int invocationCount = (int)_invocationCount;
for (int i = 0; i < invocationCount; i++)
{
- Delegate dd = (Delegate)invocationList[i];
- object[] dInvocationList = d._invocationList as object[];
+ Debug.Assert(invocationList[i] is Delegate);
+ Delegate dd = (Delegate)invocationList[i]; // If invocationList is an object[], it always contains Delegate (or MulticastDelegate) objects
+
+ object[] dInvocationList = (d._invocationList as object[])!;
if (!dd.Equals(dInvocationList[i]))
return false;
}
return true;
}
- private bool TrySetSlot(object[] a, int index, object o)
+ private bool TrySetSlot(object?[] a, int index, object o)
{
- if (a[index] == null && System.Threading.Interlocked.CompareExchange<object>(ref a[index], o, null) == null)
+ if (a[index] == null && System.Threading.Interlocked.CompareExchange<object?>(ref a[index], o, null) == null)
return true;
// The slot may be already set because we have added and removed the same method before.
@@ -160,7 +165,7 @@ namespace System
if (a[index] != null)
{
MulticastDelegate d = (MulticastDelegate)o;
- MulticastDelegate dd = (MulticastDelegate)a[index];
+ MulticastDelegate dd = (MulticastDelegate)a[index]!; // TODO-NULLABLE: Compiler should track nullability through indexers
if (dd._methodPtr == d._methodPtr &&
dd._target == d._target &&
@@ -207,7 +212,7 @@ namespace System
{
Debug.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined");
// must be a secure/wrapper one, unwrap and save
- MulticastDelegate d = (MulticastDelegate)_invocationList;
+ MulticastDelegate d = ((MulticastDelegate?)_invocationList)!;
d._methodBase = dynamicMethod;
}
else
@@ -216,9 +221,9 @@ namespace System
// This method will combine this delegate with the passed delegate
// to form a new delegate.
- protected override sealed Delegate CombineImpl(Delegate follow)
+ protected override sealed Delegate CombineImpl(Delegate? follow)
{
- if ((object)follow == null) // cast to object for a more efficient test
+ if ((object?)follow == null) // cast to object for a more efficient test
return this;
// Verify that the types are the same...
@@ -226,9 +231,9 @@ namespace System
throw new ArgumentException(SR.Arg_DlgtTypeMis);
MulticastDelegate dFollow = (MulticastDelegate)follow;
- object[] resultList;
+ object[]? resultList;
int followCount = 1;
- object[] followList = dFollow._invocationList as object[];
+ object[]? followList = dFollow._invocationList as object[];
if (followList != null)
followCount = (int)dFollow._invocationCount;
@@ -302,7 +307,8 @@ namespace System
private object[] DeleteFromInvocationList(object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
{
- object[] thisInvocationList = _invocationList as object[];
+ Debug.Assert(_invocationList is object[]);
+ object[] thisInvocationList = (object[])_invocationList;
int allocCount = thisInvocationList.Length;
while (allocCount / 2 >= invocationCount - deleteCount)
allocCount /= 2;
@@ -333,12 +339,12 @@ namespace System
// 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 override sealed Delegate RemoveImpl(Delegate value)
+ protected override sealed 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;
+ MulticastDelegate? v = value as MulticastDelegate;
if (v == null)
return this;
@@ -379,7 +385,7 @@ namespace System
int vInvocationCount = (int)v._invocationCount;
for (int i = invocationCount - vInvocationCount; i >= 0; i--)
{
- if (EqualInvocationLists(invocationList, v._invocationList as object[], i, vInvocationCount))
+ if (EqualInvocationLists(invocationList, (v._invocationList as object[])!, i, vInvocationCount))
{
if (invocationCount - vInvocationCount == 0)
{
@@ -427,7 +433,7 @@ namespace System
// 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 ==(MulticastDelegate d1, MulticastDelegate d2)
+ public static bool operator ==(MulticastDelegate? d1, MulticastDelegate? d2)
{
// Test d2 first to allow branch elimination when inlined for null checks (== null)
// so it can become a simple test
@@ -437,12 +443,12 @@ namespace System
return (d1 is null) ? true : false;
}
- return ReferenceEquals(d2, d1) ? true : d2.Equals((object)d1);
+ return ReferenceEquals(d2, d1) ? true : 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 !=(MulticastDelegate d1, MulticastDelegate d2)
+ public static bool operator !=(MulticastDelegate? d1, MulticastDelegate? d2)
{
// Can't call the == operator as it will call object==
@@ -487,7 +493,7 @@ namespace System
}
}
- internal override object GetTarget()
+ internal override object? GetTarget()
{
if (_invocationCount != (IntPtr)0)
{
@@ -528,8 +534,8 @@ namespace System
int index = (int)_invocationCount - 1;
return ((Delegate)invocationList[index]).Method;
}
- MulticastDelegate innerDelegate = _invocationList as MulticastDelegate;
- if (innerDelegate != null)
+
+ if (_invocationList is MulticastDelegate innerDelegate)
{
// must be a secure/wrapper delegate
return innerDelegate.GetMethodImpl();
@@ -548,7 +554,7 @@ namespace System
if (RuntimeTypeHandle.IsGenericTypeDefinition(declaringType) || RuntimeTypeHandle.HasInstantiation(declaringType))
{
// we are returning the 'Invoke' method of this delegate so use this.GetType() for the exact type
- RuntimeType reflectedType = GetType() as RuntimeType;
+ RuntimeType reflectedType = (RuntimeType)GetType();
declaringType = reflectedType;
}
_methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method);
@@ -572,7 +578,7 @@ namespace System
{
if (target == null)
ThrowNullThisInDelegateToInstance();
- this._target = target;
+ this._target = target!; // TODO-NULLABLE: Compiler can't see throw helper above
this._methodPtr = methodPtr;
}