[英]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;
}
我的思想過程使我相信:
但是,每當出現編輯器窗口時,我都會收到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.