protected override sealed Delegate CombineImpl(Delegate other) { if (other == null) { return(this); } MulticastDelegate o = (MulticastDelegate)other; var oInvList = o.InvocationList; var oInvLen = o.InvocationListLength; o = o.WithoutInvocationList(); // we flatten the list. var newInvList = InvocationList; var curInvLen = InvocationListLength; int newInvLen = curInvLen + 1 + oInvLen; bool needNewList = newInvList == null || newInvList.Length < newInvLen; // try appending to the current list. if (!needNewList) { //if (Interlocked.CompareExchange(ref lostInvocationList, 1, 0) != 0 /*!TakeInvokationListOwnership()*/) // The locking might acually be faster than forcing a field of the class to be volatile, // but more measurements are needed. lock (InvocationList) { if (lostInvocationList != 0) { needNewList = true; } else { lostInvocationList = 1; } } if (!needNewList) { newInvList[curInvLen] = o; for (int i = 0; i < oInvLen; ++i) { newInvList[curInvLen + i + 1] = oInvList[i]; } } } if (needNewList) { // start by 4, duplicate size. int len = newInvList == null ? 4 : newInvList.Length; while (len < newInvLen) { len *= 2; } MulticastDelegate[] list = new MulticastDelegate[len]; var curInvList = InvocationList; for (int i = 0; i < curInvLen; ++i) { list[i] = curInvList[i]; } list[curInvLen] = o; for (int i = 0; i < oInvLen; ++i) { list[curInvLen + 1 + i] = oInvList[i]; } newInvList = list; } return(this.CloneWithNewInvocationList(newInvList, newInvLen)); }