簡體   English   中英

C#:訪問靜態類實例的初始化成員將返回NULL

[英]C#:Accessing initialized member of static class instance returns NULL

我正在為Unity開發Item系統,並試圖推理XML文件操作。 我有一個ItemDatabase類,如下所示:

[XmlRoot("ItemDatabase")]
public class ItemDatabase
{
    // List that contains all Game Items.
    // Members must be Serializable. Use Editor workflow
    // to create an item Adder/Remover for the Database.
    [XmlArray("Items"), XmlArrayItem("BaseGameItem")]
    public List<BaseGameItem> Items = new List<BaseGameItem>();

    // Singleton Pattern. Only one instance will be initialized.
    public static ItemDatabase itemDb;

    public ItemDatabase()
    {
        if(itemDb == null)
        itemDb = this;
    }

    // Saves the Item List to an XML file.
    public void Save(string filepath)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(ItemDatabase));

        // Disposable Pattern
        using (FileStream stream = new FileStream(filepath, FileMode.Create))
        {
            // Check if path was valid.
            if (stream != null)
            {
                serializer.Serialize(stream, this);
                stream.Close();
            }
        }
    }

    // Loads an existing Item List from an XML file.
    public static ItemDatabase Load(string filepath)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(ItemDatabase));

        using (FileStream stream = new FileStream(filepath, FileMode.Open))
        {
            if (stream != null)
            {
                ItemDatabase db = serializer.Deserialize(stream) as ItemDatabase;
                stream.Close();
                return db;
            }

            // Return null if the file cannot be read/found.
            else
            {
                return null;
            }
        }

    }

}

最近,我接觸到了Singleton模式的一個非常基本的實現,這對我來說可以用於數據庫之類的東西。 該類的實例是靜態的,而List是在上面初始化的。

但是,然后,我嘗試使用稱為DatabaseManager類的GUI訪問此類。 相關實現如下所示:

public class ItemDatabaseManager : EditorWindow
{
    // List of items from database.
    List<BaseGameItem> items;

    // Item template to add/remove from database.
    // To be filled by user.
    BaseGameItem itemToAdd;

    private void OnEnable()
    {
        items = ItemDatabase.itemDb.Items;
    }

我的思想過程使我相信:

  1. 必須有一個ItemDatabase實例,這又意味着只有一個列表要管理。
  2. 由於列表已初始化,因此我可以從外部類(例如管理器)直接訪問它。

但是,每當出現編輯器窗口時,我都會收到Null Reference Exception,表示項目列表為null。 我已經確認這不是ItemDatabase實例。 立即將List初始化為類定義的一部分時,List怎么可能為空? 在這種情況下,我從根本上忽略了什么? 也許我誤解了構造函數的基本順序?

假設我理解得正確,將列表設置為public static可以解決-但這違背了使列表直接不可訪問的目的嗎?

實際上,由於在構造函數中創建了實例,因此您沒有正確實現單例模式。 看看這篇MSDN文章

例:

public class ItemDatabase
{
   private static ItemDatabase _instance;

   private ItemDatabase() {}

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

   // ... add the rest of your code
}

現在,您可以使用以下命令簡單地訪問單例:

ItemDatabase.Instance

實例將在首次訪問時根據需要動態創建。

編輯:根據@maccettura注釋,上面的代碼不是線程安全的。 如果需要線程安全,則可以使用鎖對象( 有關更多信息,請參見本文 ):

public class ItemDatabase
{
   private static ItemDatabase _instance;
   private static readonly object _lock = new object();

   private ItemDatabase() {}

   public static ItemDatabase Instance
   {
      get 
      {
         lock (_object)
         {
             if (instance == null)
             {
                instance = new ItemDatabase();
             }
             return instance;
         }
      }
   }

   // ... add the rest of your code
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM