diff options
author | Dan Moseley <danmose@microsoft.com> | 2019-04-01 13:53:01 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-01 13:53:01 -0700 |
commit | aebc5acdb6017676255913ba341ee9ff71f2f3ec (patch) | |
tree | 2e5282d1009f25beb9d9133744101faa7ba6899b | |
parent | d37dad3721de6cbb30424beb24383305cedfff9c (diff) | |
download | coreclr-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.resx | 3 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/Delegate.cs | 155 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/MulticastDelegate.cs | 64 |
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; } |