diff --git a/src/WinRT.Runtime/IWinRTObject.net5.cs b/src/WinRT.Runtime/IWinRTObject.net5.cs index 1bc813a05..f66a0881c 100644 --- a/src/WinRT.Runtime/IWinRTObject.net5.cs +++ b/src/WinRT.Runtime/IWinRTObject.net5.cs @@ -188,17 +188,21 @@ internal sealed bool IsInterfaceImplementedFallback(RuntimeTypeHandle interfaceT AdditionalTypeData.GetOrAdd(projectIEnum, (_) => new ABI.System.Collections.IEnumerable.AdaptiveFromAbiHelper(type, this)); } - using (objRef) + bool hasMovedObjRefOwnership = false; + + try { var vftblType = helperType.FindVftblType(); + // If there is no nested vftbl type, we want to add the object reference with the IID from the helper type + // to the cache. Rather than doing 'QueryInterface' again with the same IID, on the object reference we + // already have, we can just store that same instance in the cache, and suppress the 'objRef.Dispose()' + // call for it. This avoids that extra call, plus the overhead of allocating a new object reference. + // For all other cases, we dispose the object reference as usual at the end of this scope. if (vftblType is null) { - var qiObjRef = objRef.As(GuidGenerator.GetIID(helperType)); - if (!QueryInterfaceCache.TryAdd(interfaceType, qiObjRef)) - { - qiObjRef.Dispose(); - } + hasMovedObjRefOwnership = QueryInterfaceCache.TryAdd(interfaceType, objRef); + return true; } @@ -230,6 +234,13 @@ static IObjectReference GetObjectReferenceViaVftbl(IObjectReference objRef, Type return true; } + finally + { + if (!hasMovedObjRefOwnership) + { + objRef.Dispose(); + } + } } #if NET8_0_OR_GREATER