2023年8月9日 星期三

[C#] 沒有取消訂閱(unsubscribe)事件(Event)會導致memory leak?

 Publisher物件可提供事件供其他subscriber物件做訂閱,且一般也會在適當的時機點取消訂閱,

但如果只訂閱但沒有取消訂閱,會讓程式memory leak嗎?


我將情境分為以下4種:

1. Publisher生命週期較subscriber長,subscriber有取消訂閱。

2. Publisher生命週期較subscriber長,subscriber沒有取消訂閱。

3. Publisher生命週期較subscriber短,subscriber有取消訂閱。

4. Publisher生命週期較subscriber短,subscriber沒有取消訂閱。


Publisher使用下圖的Server類別:

Subscriber使用下圖的Log類別,Log訂閱Server的ServerConnected事件:


以下依序列出測試結果,這裡使用VS內建的記憶體快照來確認物件是否已GC:

1. Publisher生命週期較subscriber長,subscriber有取消訂閱:

    可以看到Log物件(subscriber)已經被GC了。

2. Publisher生命週期較subscriber長,subscriber沒有取消訂閱:

    可以看到Log物件(subscriber)還存在記憶體。

3. Publisher生命週期較subscriber短,subscriber有取消訂閱:

4. Publisher生命週期較subscriber短,subscriber沒有取消訂閱:

情境3跟4,都是Server物件先回收,Log物件還留著的情形,記憶體快照也是一樣結果,
代表publisher先回收的話,subscriber沒有取消事件訂閱,也沒有關係:


結論是,subscriber還是要在適當時機點取消事件訂閱,如同情境2的結果,訂閱長生命週期的事件,是會造成memory leak的。

2023年4月16日 星期日

[UML] UML的關聯(association)、依賴(dependency)與差異

 關聯(association)與依賴(dependency)是UML類別圖常用來描述類別間的關係。

 關聯的表示如下,Customer關聯Order,用實線指到目標類別:


依賴的表示如下,MessageBroker依賴MessageFormat,虛線表示:









會覺得好像有點像? 

關聯是用在A類別擁有B類別的執行個體參考,如下程式碼:


而依賴則是代表A類別在其方法內建立或使用B類別的instance,
也就是A類別並沒有保存B類別的物件。








而箭頭上的數字就代表擁有參考的數量,如下圖就代表Customer擁有多張Order。


其實關聯還有其他2個特殊形式,聚合(aggregation)與組合(composition),
不過直接用關聯表示也可以,除非真的需要特別呈現出來。