Skip to content

Instantly share code, notes, and snippets.

@myroot
Last active March 6, 2024 13:32
Show Gist options
  • Save myroot/30fa5cb9dd69a3bfee607b2721b468e0 to your computer and use it in GitHub Desktop.
Save myroot/30fa5cb9dd69a3bfee607b2721b468e0 to your computer and use it in GitHub Desktop.
C# Delegate와 HashSet 그리고 WeakReference
using System;
class Program {
delegate void MyDelegate(int v);
HashSet<object> _set = new();
WeakReference<MyDelegate> _weak;
public void Test()
{
MyDelegate d1 = (MyDelegate)Fun;
if (_weak != null && _weak.TryGetTarget(out var target)) {
Console.WriteLine($"d1 == target : {target == d1}");
Console.WriteLine($"Object.ReferenceEquals {Object.ReferenceEquals(d1, target)}");
Console.WriteLine($"d1.GetHashCode() == target.GetHashCode() : {d1.GetHashCode() == target.GetHashCode()}");
}
// if (d1 is Delegate) {
// if (_set.Contains(d1)){
// _set.Remove(d1);
// }
// }
_set.Add(d1);
_weak = new WeakReference<MyDelegate>(d1);
Console.WriteLine($"--------------- set size : {_set.Count}");
GC.Collect();
GC.Collect();
GC.Collect();
}
public void CheckWeak(){
if (_weak != null && _weak.TryGetTarget(out var target)) {
Console.WriteLine($"Weak alive: {target}");
}
else {
Console.WriteLine($"Weak dead");
}
}
public void GarbageAndGC() {
for (int i = 0 ; i <10000; i++) {
byte[] b = new byte[1000];
}
GC.Collect();
GC.Collect();
}
public void Fun(int v) {}
public static void Main(string[] args) {
Console.WriteLine("Hello world");
var p = new Program();
p.Test();
p.GarbageAndGC();
p.CheckWeak();
p.Test();
p.GarbageAndGC();
p.CheckWeak();
}
}
@myroot
Copy link
Author

myroot commented Mar 6, 2024

당황 포인트

  1. InstanceMethod로부터 만들어진 Delegate는 다 같은 객체로 만들어지는 줄 알았는데 아니네 (한 InstanceMethod로부터 한번 만들어지면 캐시되어서 같은 객체를 주는줄 알았다)
  2. Delegate가 만들어진 InstanceMethod가 alive하면 그것으로부터 만들어진 Delegate객체는 당연히 alive한줄 알았다.

그런데 둘다 아니네

매번 새로운 Delegate객체가 생성되고, Delegate lifetime은 원래 instance method의 life time과 관계가 없음
반대로 Delegate가 instance method의 this객체를 Target으로 저장하기에 instance method의 instance(this)가 Delegate에 의해서 lifetime이 expand될 수 있다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment