I am trying to make a generic singleton in C# outside of unity. The problem is that when I instantiate the player class the second time it creates the object for me. How can I do this without unity?
public abstract class Singleton<T> where T : class
{
public static T Instance;
public static T _instacene
{
get { return Instance; }
}
public Singleton()
{
if (Instance == null)
{
Instance = this as T;
Console.WriteLine(Instance.ToString());
}
else Instance = null;
}
}
Player class
public class Player : Singleton<Player>
{
public int life;
private string name;
public Player(string n)
{
this.name = n;
life = 900;
}
}
Using an underscore prefix is generally used for member fields. You named the field Instance but the property with an underscore… When using a singleton you always want to use the property. So you should swap the names.
Line 22 else Instance = null; makes no sense. Why would you set the static variable to null when a second instance is created? That would effectively make you loose both instances.
A proper singleton class should use where T : Singleton<T> as generic constraint. This gives proper inheritance support and also restricts the generic type to types derived from the Singleton base class which is generally what we want with a singleton class.
As Kurt said, singletons are almost never manually created as there is only one “single” instance of that class which should be accessed through the static property.
An ordinary thread safe C# singleton class would look like this:
public abstract class Singleton<T> where T : Singleton<T>, new()
{
private static T _Instance = new T();
public static T Instance => _Instance;
}
An example class would look like this
public class Player : Singleton<Player>
{
public string name;
}
Though for a plain C# singleton it’s actually pointless to create such a base class. Such a base class has several downsides:
It’s still not a proper singleton because a proper singleton would have a private constructor so no one could create an instance externally. This is not possible with a base class like this as here the constructore has to be public and therefore it’s not a proper singleton.
Using such a base class restricts you in the class design as you can not derive your class from any other base class.
That’s why in plain C# you would create a singleton by simply adding those two lines to a class:
public class Player
{
public static Player Instance {get; private set;} = new Player();
private Player() { }
}
This is a proper singleton. It does lazy initialize itself when first accessed. It can only be accessed through the static property. Instead of an auto property another common design is to use a simple readonly field:
public static readonly Player Instance = new Player();
Though using a getter is usually better from an interface design point of view. Interactions between classes in pure OOP should always be done through methods / properties, though you shouldn’t take those things too serious. It’s much more important to have a design where you undertand why you’re doing it that way.