2017年1月7日 星期六

[C#面試問題]Singleton instance相關問題

主要翻譯自http://www.csharpstar.com/csharp-interview-questions-part-1/,再加上我自己的一點想法。

What is the difference between Static class and Singleton instance?

– In c# a static class cannot implement an interface. When a single instance class needs to implement an interface for some business reason or IoC purposes, you can use the Singleton pattern without a static class.
– You can clone the object of Singleton but, you can not clone the static class object
– Singleton object stores in Heap but, static object stores in stack
– A singleton can be initialized lazily or asynchronously while a static class is generally initialized when it is first loaded

Static class和Singleton instance有什麼不同?
Singleton的意思就是程式中只能有一個實體。
  1. 在C#當中,static class無法實作interface。如果一個single instance class需要實做一個interface,或是需要控制反轉(IoC)的時候,你可以使用Singleton instance而不需要static class。
    *控制反轉我覺得這篇文章(用超人的故事讲解 IoC(控制反转) 和 DI(依赖注入))講得蠻清楚的。
  2. 在Singleton instance中物件是可以被複製的,但是static class則不行。
  3. Singleton instance裡的物件是存在heap(堆積),而static class則是存在stack(堆疊)。
    在Memory的管理中,物件內容會存放於Heap,而物件參考(指標)是存放於Stack。部分程式語言(像是比較早期的objective-C 或是C++)Heap是需要自己釋放記憶體空間的,而C#則是用了CLR來接管heap,加上GC原則上是不用自己去釋放,但是還是會有memory leak的可能,最明顯的例子就是office interop這種COM+ object,或是SharePoint的SPSite。(不知道SharePoint2016有沒有改善)
    比方說我們可以從以下的code來看物件在heap中的生命週期:
    Cat cat = new Cat();
    
    Cat.Name = "Sumomo";
    
    public void ChangeName(Cat c)
    {
        c.Name = "Sora";
    }
    
    在這邊ChangeName function傳入的變數c並不是Cat的值,而是point,所以當進入ChangeName的時候在heap中會有兩個point,都指向Cat。而修改值只是修改heap中的參考,當離開function之後就進入ChangeName function的物件就會被回收。

    另外在C#當中Stack中存放參數(value),Heap存放物件(reference type)。比方說,int x = 42;這段語法會在stack中存放一個42的值。
    如果我們再建立一個object指向x
    object o = x;
    這時候x轉換成o時是將x變數的值複製一份到o在Heap 裡的空間,這個作業稱為boxing。如果我們再把object o再轉一次放進另一個變數y
    int y = (int)o;
    這時就會再把o的值複製一份到stack中,這個動作稱之為unboxing
    *String是例外,所有的string都是reference type。
  4. Singleton instance可以initialize lazily或是非同步執行,而static class則是會在第一次執行的時候被初始化。

Why singleton pattern is considered an Anti-pattern ?

– Singletons aren’t easy to handle with unit tests. You can’t control their instantiation and they may retain state across invocations.
– Memory allocated to an Singleton can’t be freed.
– In multithreaded environment, access to the singleton object may have to be guarded (e.g. via synchronization).
– Singletons promote tight coupling between classes, so it is hard to test
 為什麼Singleton instance被認為是一種Anti-pattern?
  1.  Singleton instance不容易做unit test,因為你無法控制它的實作,又很容易殘留。
  2. 在 Singleton instance中allocate的記憶體無法被回收
  3.  在多執行緒的環境當中,如果用到Singleton物件可能會被鎖定,造成資源競爭。是可以加上同步的機制,但會造成效能低落。雖然可以透過Lazy Instantization,但這並不是thread-safe的寫法。
  4.  Singleton instance會造成class之間的高度耦合,所以不容易測試。

結語
Singleton instance不是不能用,只是設計的時候要更小心,在對的地方使用。

1 則留言:

lingmaaki 提到...

check this one...

http://net-informations.com/faq/default.htm