public sealed override bool Equals([NotNullWhen(true)] object?obj) { if (obj == null) { return(false); } if (object.ReferenceEquals(this, obj)) { return(true); } if (!InternalEqualTypes(this, obj)) { return(false); } // Since this is a MulticastDelegate and we know // the types are the same, obj should also be a // MulticastDelegate Debug.Assert(obj is MulticastDelegate, "Shouldn't have failed here since we already checked the types are the same!"); var d = Unsafe.As <MulticastDelegate>(obj); // there are 2 kind of delegate kinds for comparison // 1- Multicast (m_helperObject is Delegate[]) // 2- Single-cast delegate, which can be compared with a structural comparison IntPtr multicastThunk = GetThunk(MulticastThunk); if (m_functionPointer == multicastThunk) { return(d.m_functionPointer == multicastThunk && InvocationListEquals(d)); } else { if (!object.ReferenceEquals(m_helperObject, d.m_helperObject) || (!FunctionPointerOps.Compare(m_extraFunctionPointerOrData, d.m_extraFunctionPointerOrData)) || (!FunctionPointerOps.Compare(m_functionPointer, d.m_functionPointer))) { return(false); } // Those delegate kinds with thunks put themselves into the m_firstParameter, so we can't // blindly compare the m_firstParameter fields for equality. if (object.ReferenceEquals(m_firstParameter, this)) { return(object.ReferenceEquals(d.m_firstParameter, d)); } return(object.ReferenceEquals(m_firstParameter, d.m_firstParameter)); } }
public override sealed bool Equals(Object obj) { if (obj == null || !InternalEqualTypes(this, obj)) { return(false); } MulticastDelegate d = obj as MulticastDelegate; if (d == null) { return(false); } // there are 2 kind of delegate kinds for comparision // 1- Multicast (m_helperObject is Delegate[]) // 2- Single-cast delegate, which can be compared with a structural comparision if (m_functionPointer == GetThunk(MulticastThunk)) { return(InvocationListEquals(d)); } else { if (!Object.ReferenceEquals(m_helperObject, d.m_helperObject) || (!FunctionPointerOps.Compare(m_extraFunctionPointerOrData, d.m_extraFunctionPointerOrData)) || (!FunctionPointerOps.Compare(m_functionPointer, d.m_functionPointer))) { return(false); } // Those delegate kinds with thunks put themselves into the m_firstParamter, so we can't // blindly compare the m_firstParameter fields for equality. if (Object.ReferenceEquals(m_firstParameter, this)) { return(Object.ReferenceEquals(d.m_firstParameter, d)); } return(Object.ReferenceEquals(m_firstParameter, d.m_firstParameter)); } }