From 36ca20dff3a61baccec6ab2adb6d8e64d9b83695 Mon Sep 17 00:00:00 2001 From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:54:03 -0600 Subject: [PATCH] Reworked WeakReferenceKey.Equals() --- .../Caching/WeakReferenceKey.cs | 9 ++++++++- .../Cache/WeakReferenceKeyTests.cs | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Caching/WeakReferenceKey.cs b/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Caching/WeakReferenceKey.cs index ad1adc172..7e69df470 100644 --- a/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Caching/WeakReferenceKey.cs +++ b/src/Agent/NewRelic/Agent/Extensions/NewRelic.Agent.Extensions/Caching/WeakReferenceKey.cs @@ -24,6 +24,13 @@ public override bool Equals(object obj) { if (obj is WeakReferenceKey otherKey) { + if (WeakReference.TryGetTarget(out var thisTarget) && + otherKey.WeakReference.TryGetTarget(out var otherTarget)) + { + return ReferenceEquals(thisTarget, otherTarget); + } + + // if one of the targets has been garbage collected, we can still compare the hashcodes return otherKey.GetHashCode() == _hashCode; } @@ -32,7 +39,7 @@ public override bool Equals(object obj) public override int GetHashCode() { - return _hashCode; + return WeakReference.TryGetTarget(out var target) ? target.GetHashCode() : _hashCode; } /// diff --git a/tests/Agent/UnitTests/NewRelic.Agent.Extensions.Tests/Cache/WeakReferenceKeyTests.cs b/tests/Agent/UnitTests/NewRelic.Agent.Extensions.Tests/Cache/WeakReferenceKeyTests.cs index 283b4cf55..f73d6d271 100644 --- a/tests/Agent/UnitTests/NewRelic.Agent.Extensions.Tests/Cache/WeakReferenceKeyTests.cs +++ b/tests/Agent/UnitTests/NewRelic.Agent.Extensions.Tests/Cache/WeakReferenceKeyTests.cs @@ -150,6 +150,26 @@ public async Task Equals_ShouldReturnFalseIfTargetIsGarbageCollected() Assert.That(weakRefKey1.Equals(weakRefKey2), Is.False); } + [Test] + public async Task GetHashCode_ShouldReturnOriginalHashcodeIfTargetIsGarbageCollected() + { + // Arrange + var weakRefKey = GetWeakReferenceKey(); + var originalHashCode = weakRefKey.GetHashCode(); + + // Act + Assert.That(weakRefKey.Value, Is.Not.Null); + + // force garbage collection + GC.Collect(); + GC.WaitForPendingFinalizers(); + await Task.Delay(500); + GC.Collect(); // Force another collection + + // Assert + Assert.That(weakRefKey.Value, Is.Null); // ensure GC really happened + Assert.That(weakRefKey.GetHashCode(), Is.EqualTo(originalHashCode)); + } private class Foo { public string Bar { get; set; }