I'm using ConditionalWeakTable
for the purpose of loosely holding references instead of strongly referencing using a traditional lookup like Dictionary
.
However I've tested one case to double-check that capability and looks like it's failed. The following code is based on Windows Forms
however you can try adjusting it using any framework or platform you want:
The sample models:
public class SampleModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string property = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
string _name;
public string Name
{
get
{
return _name;
}
set
{
if(_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
}
Main code:
//at some class level scope
BindingSource _bs;
ConditionalWeakTable<BindingSource, object> _lookup =
new ConditionalWeakTable<BindingSource, object>();
public void Test(){
_bs = new BindingSource();
var item = new SampleModel();
_bs.Add(item);
_bs.ListChanged += (s,e) =>
{
MessageBox.Show("Failed! There is some memory leak");
};
_lookup.Add(_bs, new object());
//here the old instance is not referenced by any variable
_bs = new BindingSource();
//try collecting all collectable things
GC.Collect();
GC.WaitForPendingFinalizers();
//try changing the item's property
//the old instance of BindingSource if not collected will still
//fire the ListChanged event and the handler will show a message box
//as you see above.
item.Name = "some name";
}
The testing app is built in Release mode to ensure that the GC works correctly.
And the result is the message box always shows.
The expected result is no message box shown.
Note that the Test
method is run just once for each time running the testing app.
Could you please explain something wrong here?