I have several MonoBehavior subclasses that need to be a Singleton however assigning an Instance property in Awake() is too late for some classes and results in race conditions so I was wondering is there anything that speaks against assigning Instance in a private c-tor, like this:
public class Foo: MonoBehaviour
{
public static Foo Instance { get; private set; }
private Foo()
{
Instance = this;
}
}
Or are there any negative side effects to this approach that I need to be aware of?
I agree with Lorek's answer but there is one problem with it.
You shouldn't use the constructor of a MonoBehavior as that itself has undesired behaviors. Since it will not be part of a specific GameObject. So you will have to add it to the Init, Awake or Start method of that Behavior; Or create a new class to contain the logic you want to share. (The new class should not be extended by the MonoBehavior class)
And then create a singleton as Lorek describes above.
You could also change the Script Execution Order to make sure that your MonoBehavior that needs to work as a "singleton" being executed before all other scripts.
However, it will be necessary to already have this MonoBehavior attached to an existing GameObject in the scene and not added automatically/by code.
http://docs.unity3d.com/Manual/class-ScriptExecution.html
The technique you are using allows the Instance property to be set more than once, even though if only by other members of the same class. That is a no-no. I would do something like this:
private static readonly Foo instance = new Foo();
public static Foo Instance
{
get
{
return instance;
}
}
This is a simple way to be certain the singleton variable is set only once. If you want lazy instantiation you could do something like this:
private static Foo instance = null;
public static Foo Instance
{
get
{
if (null == instance)
instance = new Foo();
return instance;
}
}
But with this technique you could still write to your instance variable more than once. So, you'll need to make sure you always reference the property and not the variable. And if this property is going to be accessed from multiple threads you'll want to prevent race conditions by using a critical section like this:
private static readonly object singletonSection = new object();
private static Foo instance = null;
public static Foo Instance
{
get
{
if (null == instance)
{
lock(singletonSection)
{
if (null == instance)
instance = new Foo();
}
}
return instance;
}
}
This is the double-checked locking pattern. You could use regular locking if the code is not accessed much and/or performance is not a problem.
Thanks for the input anyone! I eventually came up with the following method because in my case those Singletons are created via the Editor (from a menu) and the singletons should be components on a container game object.
public static T GetInstance<T>(string containerName) where T : Component
{
/* Find container or create if it doesn't exist. */
var container = GameObject.Find(containerName);
if (container == null) container = new GameObject(containerName);
/* Get existing instance or create new one if not found. */
return container.GetComponent<T>() ?? container.AddComponent<T>();
}
Of course it's not perfect either because it relies only on object names. But it works for me.
MonoSingleton class is useful if you need to have a single global MonoBehaviour script accessible from anywhere. Here is the MonoSingleton class:
using UnityEngine;
public class MonoSingleton<T> where T : MonoBehaviour
{
private static T _instance;
private static bool isFound;
private bool createMissingInstance;
static MonoSingleton()
{
isFound = false;
_instance = null;
}
public MonoSingleton(bool createNewInstanceIfNeeded = true)
{
this.createMissingInstance = createNewInstanceIfNeeded;
}
public T Instance
{
get
{
if (isFound && _instance)
{
return _instance;
}
else
{
UnityEngine.Object[] objects = GameObject.FindObjectsOfType(typeof(T));
if (objects.Length > 0)
{
if (objects.Length > 1)
Debug.LogWarning(objects.Length + " " + typeof(T).Name + "s were found! Make sure to have only one at a time!");
isFound = true;
_instance = (T) System.Convert.ChangeType(objects[0], typeof(T));
return _instance;
}
else
{
Debug.LogError(typeof(T).Name + " script cannot be found in the scene!!!");
if (createMissingInstance)
{
GameObject newInstance = new GameObject(typeof(T).Name);
isFound = true;
_instance = newInstance.AddComponent<T>();
Debug.Log(typeof(T).Name + " was added to the root of the scene");
return _instance;
}
else
{
isFound = false;
return null; // or default(T)
}
}
}
}
}
}
Then define MonoSingletons inside a static class. For example:
public static class Global
{
public static MonoSingleton<GameProgress> progress = new MonoSingleton<GameProgress>(true); //true means that new GameObject with script GameProgress will be created if it is missing from the scene
public static MonoSingleton<CharacterController> characterController = new MonoSingleton<CharacterController>(false); //will return null if there is no character controller present in the scene.
}
And then simply access global MonoBehaviors from any script!
Global.progress.Instance.score++;
Related
I'm trying to instantiate an object with a singleton in c#.
private static Mario __instance;
public static Mario Instance
{
get
{
if (__instance == null)
{
__instance = new Mario(); //TODO correct this vector
}
return __instance;
}
}
public Mario()
{
position = Vector2.Zero;
theatre = XNATheatre.Theatre;
ActionState = new IdleState();
PreviousState = ActionState;
ActionState.Enter(null);
isFacingRight = true;
}
I also have an idlestate class that is being instantiated in mario's constructor:
public IdleState()
{
mario = Mario.Instance;
Console.WriteLine(mario);
}
What seems to be happening is the _instance variable in my singleton always remains null, therefore it keeps returning new instances of mario, exactly the opposite of what I want it to do. I'm not exactly sure how to get around this.
You have a circular dependency...
When instantiating a Mario you instantiate an IdleState which calls Mario.Instance instantiating a new Mario and repeat.
According to Jon Skeet's article, the following pattern is bad as it is not thread safe.
// Bad code! Do not use!
public sealed class Singleton
{
private static Singleton instance = null;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
I have not learnt threading yet so it is a bit abstract to me. Could you give me a simple code to simulate the threading problem (we get notified when the problem occurs)?
Well thats pretty simple, just let something access a property within your singleton in parallel, for example like this console app.
class Program
{
static void Main(string[] args)
{
var threads = Enumerable.Repeat(new Action(() => Console.WriteLine(Singleton.Instance.guid)), 10);
Parallel.ForEach(threads, t => t());
Console.Read();
}
}
(I've added a guid property to your class to test that)
public sealed class Singleton
{
public Guid guid = Guid.NewGuid();
private static Singleton instance = null;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
The issue with this singleton implementation is that 2 threads can access the getter simultaneously and each one will create a new instance. So the first thread might end up with a different instance than the second one... which can lead to unexpected behavior.
This is just in reply to OP comment:
static void Main(string[] args)
{
int test = 5;
Task<Singleton>[] arr =
{
Task<Singleton>.Factory.StartNew(() => Singleton.Instance),
Task<Singleton>.Factory.StartNew(() => Singleton.Instance),
};
Task.WaitAll(arr);
foreach (var item in arr)
{
Singleton s = item.Result;
s.MyProperty = test++;
Console.WriteLine(s.MyProperty);
}
}
MyProperty is just an int property i added.
I have a class which implements the Singleton design pattern. However, whenever i try to get an instance of that class, using Activator.CreateInstance(MySingletonType) only the private constructor is called. Is there any way to invoke other method than the private constructor?
My class is defined as follow:
public class MySingletonClass{
private static volatile MySingletonClassinstance;
private static object syncRoot = new object();
private MySingletonClass()
{
//activator.createInstance() comes here each intantiation.
}
public static MySingletonClassInstance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new MySingletonClass();
}
}
return instance;
}
}
}
And the instantiation as follow:
Type assemblyType = Type.GetType(realType + ", " + assemblyName);
IService service = Activator.CreateInstance(assemblyType, true) as IService;
Activator.CreateInstance, except for one extreme edge-case, always creates a new instance. I suggest that you probably dont want to use Activator here.
However, if you have no choice, the hacky hack hack hack is to make a class that inherits from ContextBoundObject, and decorate it with a custom subclass of ProxyAttribute. In the custom ProxyAttribute subclass, override CreateInstance to do whatever you want. This is all kinds of evil. But it even works with new Foo().
Hei i do not know why are you creating an object of singleton class using reflection.
the basic purpose of singleton class is that it has only one object and has global access.
however you can access any of your method in singleton class like :
public class MySingletonClass {
private static volatile MySingletonClass instance;
private static object syncRoot = new object();
private MySingletonClass() { }
public static MySingletonClass MySingletonClassInstance {
get {
if (instance == null) {
lock (syncRoot) {
if (instance == null)
instance = new MySingletonClass();
}
}
return instance;
}
}
public void CallMySingleTonClassMethod() { }
}
public class program {
static void Main() {
//calling a
methodMySingletonClass.MySingletonClassInstance
.CallMySingleTonClassMethod();
}
}
I am struggling with using Singleton design pattern. I am trying to use it in this simple console application. I have a problem with it in the Main method in Program class. I want to define object from the Singleton class such as: var data = Singleton.Instance; but I don't know why I can't do that
Also, I don't know why I am getting the following error message when I run the program:
Unhandled Exception: System.NullRefernceException: Object reference not
set to an instance of an object.
So how to fix that?
Singleton Class:
namespace Singleton
{
class Singleton
{
//Variable
private static Singleton instance;
private List<string> Messages;
//Constructor
private Singleton() { }
//Property
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
//Methods
public void Message(string message)
{
Messages.Add(message);
}
public bool HasMessage(string message)
{
return Messages.Contains(message);
}
}
}
Program Class:
namespace Singleton
{
class Program
{
static void Main(string[] args)
{
var data = Singleton.Instance;
Singleton.Instance.Message("Hello World!!!");
if(Singleton.Instance.HasMessage("12"))
Console.WriteLine("NO STRING!!!");
else
Console.WriteLine("There is a match");
}
}
}
UPDATE:
Guys, I really appreciate your help so far. The program is working now but the logic is not working. If you look at the main program, you will see that the list only has "Hello World!!!". However, when I used the HasMessage method doesn't work. Because the program keeps showing "There is a match". But it should show me "NO STRING!!!" as there is no match. So how to fix that?
Your field Messages is not initialized to anything. That is why you are getting the exception. In your class do:
private List<string> Messages = new List<string>();
You may also look at Thread Safe Singleton implementation by Jon Skeet
EDIT:
Based on the updated question. Your Check and Message are opposite. It should be:
if (Singleton.Instance.HasMessage("12"))
Console.WriteLine("There is a match");
else
Console.WriteLine("NO STRING!!!");
Your method HasMessage returns true if the passed parameter is present in the list and false otherwise.
It looks like you're almost there. Consider rewriting your code like this:
class Singleton
{
//Variable
private static Singleton Instance;
private List<string> Messages;
//Constructor
private Singleton()
{
Messages = new List<string>(); //Make sure to instantiate instance types before use.
}
//Property
public static Singleton GetInstance()
{
if (Instance == null)
{
Instance = new Singleton();
}
return Instance;
}
//Methods
public void Message(string message)
{
Messages.Add(message);
}
public bool HasMessage(string message)
{
return Messages.Contains(message);
}
}
There are some helpful C# tutorials for design patterns on this site.
However, when I used the HasMessage method doesn't work. Because the program keeps showing "There is a match". But it should show me "NO STRING!!!" as there is no match. So how to fix that?
This should really be a separate question, but I'll answer it anyway. You've got your condition backwards. Your code is says to write "no string" if the instance does contain the message "12", and "There is a match" if it does not. Try this:
if(Singleton.Instance.HasMessage("12"))
Console.WriteLine("There is a match");
else
Console.WriteLine("NO STRING!!!");
private List<String> Messages;
Here is your problem. The member has never been instanciated in your code. You could do as follows:
//Constructor
private Singleton()
{
Messages = new List<string>();
}
Also i suggest you to use proper naming conventions for your local variables and members. Change instance to m_Instance and Messages to m_Messages. Also try to implement singletons in a thread-safe way... for more informations look at this page.
That's the implementation of Singleton:
public sealed class SingletonExample
{
//static Field
private static SingletonExample _seInstance = null;
private int _nCounter = 0;
// private constructor
private SingletonExample() { _nCounter = 1; }
//public static get(), with creating only one instance EVER
public static SingletonExample SeInstance
{
get { return _seInstance ?? (_seInstance = new SingletonExample()); }
}
}
How to invoke and create an instance?
SingletonExample si1 = SingletonExample.SeInstance;
SingletonExample si2 = SingletonExample.SeInstance; // it will be the same object
System.Diagnostics.Debug.WriteLine(si1.Equals(si2));// TRUE
Currently I have the following class:
public class PluginManager
{
private static bool s_initialized;
private static object s_lock = new object();
public static void Initialize() {
if (!s_initialized) {
lock (s_lock) {
if (!s_initialized) {
// initialize
s_initialized = true;
}
}
}
}
}
The important thing here is that Initialize() should only be executed once whilst the application is running. I thought that I would refactor this into a singleton class since this would be more thread safe?:
public sealed class PluginService
{
static PluginService() { }
private static PluginService _instance = new PluginService();
public static PluginService Instance { get { return _instance; } }
private bool s_initialized;
public void Initialize() {
if (!s_initialized)
{
// initialize
s_initialized = true;
}
}
}
Question one, is it still necessary to have the lock here (I have removed it) since we will only ever be working on the same instance?
Finally, I want to use DI and structure map to initialize my servcices so I have refactored as below:
public interface IPluginService {
void Initialize();
}
public class NewPluginService : IPluginService
{
private bool s_initialized;
public void Initialize() {
if (!s_initialized) {
// initialize
s_initialized = true;
}
}
}
And in my registry:
ForRequestedType<IPluginService>()
.TheDefaultIsConcreteType<NewPluginService>().AsSingletons();
This works as expected (singleton returning true in the following code):
var instance1 = ObjectFactory.GetInstance<IPluginService>();
var instance2 = ObjectFactory.GetInstance<IPluginService>();
bool singleton = (instance1 == instance2);
So my next question, is the structure map solution as thread safe as the singleton class (second example). The only downside is that this would still allow NewPluginService to be instantiated directly (if not using structure map).
Many thanks,
Ben
I would make several recommendations:
the boolean flag should be volatile
make your singleton instance readonly
the initialization is not thread safe, regardless of the fact that you have only one instance... so it should be synchronized
public sealded class PluginService
{
static PluginService() { }
//make the instance readonly
private static readonly PluginService _instance = new PluginService();
public static PluginService Instance { get { return _instance; } }
// make the flag volatile
private static volatile bool s_initialized = false;
private static object s_lock = new object();
// you still need to synchronize when you're initializing
public void Initialize() {
lock(s_lock)
{
if (!s_initialized)
{
// initialize
s_initialized = true;
}
}
}
}
There is no contention on the structured map, so its thread safety doesn't seem compromised...
The singleton class you had was not thread safe. The main thing to remember is that a single instance does not ensure a single thread can only access it. If there are multiple threads that have a reference to the instance, then there is contention on the instance and the data it's holding. If there is contention then you should ensure thread safety (synchronize at the very minimum).