1

我有這樣定義的單例:當使用單例模式時,我的公共類是否應返回私有或公共實例?

public partial class MoonDataManager 
{ 

    static MoonDataManager _singletonInstance; 
    public static MoonDataManager SingletonInstance 
    { 
     get 
     { 
      return _singletonInstance; 
     } 
     private set 
     { 
      _singletonInstance = value; 
     } 
    } 

我有平安創建實例的函數:

public static async Task<MoonDataManager> CreateSingletonAsync() 
    { 
      _singletonInstance = new MoonDataManager(); 

我應該:

return _singletonInstance; (field) 

return SingletonInstance; (property) 

我很關心垃圾收集,尤其是Xamarin中的iOS或Android。

此外,如果在C#中有這樣的命名模式,請告訴我是否偏離標準。


更新:

現在,我想我真的有我自己堅持的線程和異步方法。下面是對象和他們的目標:

  • MoonDataManager:運行RegisterTable<Models.IssuerKey>每桌一次。這是一種基本運行的通用方法(new MobileServiceSQLiteStore).DefineTable<T>()

  • OfflineStore:這是一個MobileServiceSQLiteStore

  • MobileClient:這是一個MobileServiceClient

  • MoonDataManager相關性:MoonDataManager需要OfflineStore和MobileClient完成初始化。具體而言,它確實MobileServiceClient .SyncContext.InitializeAsync(OfflineStore

我不知道如何使某種意義上說,這麪條依賴的...或如何使代碼看起來不錯,並且是線程安全的。

這裏是代碼的新的迭代:

private readonly Lazy<MobileServiceClient> lazyMobileClient = 
     new Lazy<MobileServiceClient>(() => new MobileServiceClient(Constants.ApplicationURL), true); // true for thread safety 
    public MobileServiceClient MobileClient { get { return lazyMobileClient.Value; } } 


    private readonly Lazy< MobileServiceSQLiteStore> offlineDB = 
     new Lazy<MobileServiceSQLiteStore>(() => new MobileServiceSQLiteStore(Constants.OfflineDBName), true); // true for thread safety 
    private MobileServiceSQLiteStore OfflineStore { get { return offlineDB.Value; } } 

    private static readonly Lazy<MoonDataManager> lazy = new Lazy<MoonDataManager>(() => new MoonDataManager(), true); // true for thread safety 
    public static MoonDataManager Instance { get { return lazy.Value; } } 

    private MoonDataManager() 
    { 

      MoonDataManager.Instance.RegisterTable<Models.IssuerKey>(); 

      // Initialize file sync 
      // todo: investigate FileSyncTriggerFactory overload. 
      //Was present on Mar 30, 2016 Channel9 https://channel9.msdn.com/events/Build/2016/P408 
      MoonDataManager.Instance.MobileClient.InitializeFileSyncContext 
          (new IssuerKeyFileSyncHandler(Instance), Instance.OfflineStore); 

      // NOTE THE ASYNC METHOD HERE (won't compile) 
      await MoonDataManager.Instance.MobileClient 
           .SyncContext.InitializeAsync(MoonDataManager.Instance.OfflineStore, 
           StoreTrackingOptions.NotifyLocalAndServerOperations); 

    } 
+1

僅供參考這不是線程安全的方式。閱讀[this](http://csharpindepth.com/Articles/General/Singleton.aspx) – CodingYoshi

+0

僅供參考 - 我也在試驗這種方法:https://forums.xamarin.com/discussion/25881/using-async -in-xamarin-forms(評論由rene_ruppert) – LamonteCristo

回答

0

您應該返回私有實例。你可以在MSDN上閱讀關於單身模式的更多信息。標準的單例實現如下:

public class Singleton 
{ 
    private static Singleton instance; 

    private Singleton() {} 

    public static Singleton Instance 
    { 
     get 
     { 
      if (instance == null) 
      { 
      instance = new Singleton(); 
      } 
      return instance; 
     } 
    } 
} 

雖然,通常情況下,您沒有該屬性的setter。這種模式有already previously been discussed on SO

+1

這不是線程安全的,只是一個fyi – CodingYoshi

+0

True @CodingYoshi。如果多線程是一個問題,應該使用'lock'。該模式也在我從MSDN附加的鏈接中描述。但是這個問題沒有描述這個問題,所以我忽略了這個事實。 – Demitrian

+0

這是因爲什麼原因被投票?它很好地回答了這個問題。 – Demitrian

3

定義

static MoonDataManager _singletonInstance; 

確保的MoonDataManager的實例是一個GC根,並且它不會被收集,直到應用程序結束域,because it is a static value


我會返回私人單身人士,並放棄您擁有的汽車財產。

public partial class MoonDataManager 
{ 
    private static readonly Lazy<MoonDataManager> _manager = 
     new Lazy<MoonDataManager>(() => new MoonDataManager()); 

    public static MoonDataManager SingletonInstance => _manager.Value; 
} 

MoonDataManager.Value的首次訪問,它使用的是傳遞給構造函數Lazy<T>Func<MoonDataManager>初始化。在後續訪問中,返回相同的實例。

+0

我剛在問題中更新了我的代碼,並對此進行了擴展。 – LamonteCristo

3

單身創建自己的第一次它的訪問,以確保只有一個實例將獲得創建一種方式,即使第二個線程試圖訪問它,同時它還是被實例化

您CreateSingletonAsync()違反本,看起來像它會允許多線程污穢

你想要的東西,如:

public static MoonDataManager SingletonInstance 
{ 
    get 
    { 
     if (_singletonInsatnce != null) 
      return _singletonInstance; 
     lock (lockobject) 
     { 
      // check for null again, as new one may have been created while a thread was waiting on the lock 
      if (_singletonInsatnce != null) 
       return _singletonInstance; 
      else 
       // create new one here. 
     } 
    } 
    // no setter, because by definition no other class can instantiate the singleton 
} 

這一切只是爲了確保兩個線程請求一個對象最終不會創建兩個對象, 或者 第二個線程獲取一個半創建的對象,如果第一個線程的仍然被創建。

注意:單身人士已經變得不合時宜。

注意:如果您確定在訪問對象之前有足夠的時間來創建對象,則可以使用靜態成員並在應用程序啓動時創建它。

您的問題「我應該返回屬性還是字段」沒有意義 - 您已經從屬性getter返回字段,這是標準實踐。你還想要什麼東西回來?

+0

如果Singleton'ctor'包含異步方法,我該如何利用它?什麼是單身人士更好的選擇? – LamonteCristo

+0

我剛剛更新了問題中的代碼,並對此進行了擴展。 – LamonteCristo

5

對於.NET 4或更高版本,您可以使用Lazy<T>並像這樣創建它。

public sealed class Singleton 
{ 
    private static readonly Lazy<Singleton> lazy = 
     new Lazy<Singleton>(() => new Singleton(), true); // true for thread safety 

    public static Singleton Instance { get { return lazy.Value; } } 

    private Singleton() 
    { 
    } 
} 

只有當它被訪問,只在第一時間和它是線程安全的將創建。

+0

如果Singleton'ctor'包含異步方法,我該如何利用這一點? – LamonteCristo

+0

我剛剛更新了問題中的代碼,並對此進行了擴展。 – LamonteCristo

相關問題