It seems the following code to unit test `WeakReference` does not work correctly/reliably:

```
object realObject = new object();
WeakReference weakReference = new WeakReference(realObject);
Assert.NotNull(weakReference.Target);
realObject = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Assert.Null(weakReference.Target);

```

The testing is run targeting both net461 and net5.0, for both DEBUG and RELEASE mode. The best result:

* Targeting net461: the above code runs successfully, for both DEBUG and RELEASE mode.
* Targeting net5.0: the above code fails for both DEBUG and RELEASE mode at first. After reading this post ([Garbage collection behaviour difference between .NetFramework 4.8 and .Net 5](https://stackoverflow.com/questions/69616548/garbage-collection-behaviour-difference-between-netframework-4-8-and-net-5)) it works running in RELEASE mode by adding `<TieredCompilation>false</TieredCompilation>` to `.csproj`.

So the problem narrows down to **targeting net5.0 DEBUG mode**.

I also came across the following posts but it seems they're not very helpful mostly because they're out-of-date:

* [Unit Testing Code with WeakReference](https://stackoverflow.com/questions/15062308/unit-testing-code-with-weakreference)
* [Testing/Verifying a WeakReference](https://stackoverflow.com/questions/5912797/testing-verifying-a-weakreference)

Worth to mention the answer from @Eric Lippert for [Why C# Garbage Collection behavior differs for Release and Debug executables?](https://stackoverflow.com/questions/37462378/why-c-sharp-garbage-collection-behavior-differs-for-release-and-debug-executable) says: You **absolutely cannot** rely on the garbage collector having **any particular behaviour whatsoever** with respect to the lifetime of a local, which suggests testing a WeakReference cannot be done reliably.

Edit: More information about the context of why using a `WeakReference`:

I'm developing a framework providing class `Entity<T>` and `Record<T>` similar to `System.Data.DataRow` and `System.Data.DataRowView`, with the most significance that the prior one is strongly typed. Entity is the model provides its own event to notify changes, `Record<T>` is a viewmodel that wraps `Entity<T>` to translate the change event into `INotifyPropertyChanged` plus other things such as databinding, validations, etc. `Entity<T>` should not aware the existence of `Record<T>`. To avoid memory leak, `Record<T>` should be GC reclaimed when only Entity is still referenced.

The example code for the event hookup:

`IEntityListener` Implemented by `Record<T>` class:

```
internal interface IEntityListener
{
    void OnFieldUpdated(FieldUpdatedEventArgs e);
}

```

`WeakEntityListner` to do the event hookup:

```
internal sealed class WeakEntityListener
{
    private readonly WeakReference<IEntityListener> _weakListener;
    private readonly Entity _entity;

    internal WeakEntityListener(Entity entity, IEntityListener listener)
    {
        _entity = entity;
        _weakListener = new (listener);
        _entity.FieldUpdated += OnFieldUpdated;
    }

    private void OnFieldUpdated(object? sender, FieldUpdatedEventArgs e)
    {
        if (_weakListener.TryGetTarget(out var listener))
            listener.OnFieldUpdated(e);
        else
            CleanUp();
    }

    private void CleanUp()
    {
        _entity.FieldUpdated -= OnFieldUpdated;
    }
}

```

I would like to have method `OnFieldUpdated` and `CleanUp` fully covered by unit test.