0

Is there a way to check from within a function if an argument is a static variable?

This would help me prevent any possibility of typos where the user tries to quickly setup a singleton, but forgets to declare his own instance member as static before supplyng it to us via ref

here is my function:

// returns 'false' if failed, and the object will be destroyed.
// Make sure to return from your own init-function if 'false'.
public static bool TrySet_SingletonInstance<T>(this T c,  ref T instance) where T : Component {

    //if(instance is not static){ return false } //<--hoping for something like this

    if(instance != null){  
        /* cleanup then return */
        return false;  
    }
    instance = c;
    return true;
}
Kari
  • 1,244
  • 1
  • 13
  • 27
  • well, if not possible, - one way to do this would be to use a different argument-name. For example `ref T instance_VERIFY_IS_STATIC`. Yes, ugly, but will sober-up anyone who tries to use our function – Kari Nov 30 '18 at 23:43
  • I think you can use reflection to get information about T see: https://stackoverflow.com/questions/196936/reflection-and-generic-types – Thom Kiesewetter Dec 01 '18 at 00:04

1 Answers1

2

If we assume that your singleton classes have one and only one static instance (which makes sense, since it's singleton), we can find the field using the type. In which case there is actually no need to pass it in a reference to it at all. And since we know how to get the FieldInfo, we can tell if it is static via Reflection.

public static bool TrySet_SingletonInstance<T>(this T c) where T : Component
{
    //Find a static field of type T defined in class T 
    var target = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public).SingleOrDefault(p => p.FieldType == typeof(T));

    //Not found; must not be static or public, or doesn't exist. Return false.
    if (target == null) return false;

    //Get existing value
    var oldValue = (T)target.GetValue(null);

    //Old value isn't null. Return false.
    if (oldValue != null) return false;

    //Set the value
    target.SetValue(null, c);

    //Success!
    return true;
}

Usage:

var c = new MySingleton();
var ok = c.TrySet_SingletonInstance();
Console.WriteLine(ok);

See a working example here: DotNetFiddle

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • 1
    What I fail to understand, why would you have a method to set the singleton instead of having the singleton assignment in the ctor? I don't see the added value in this. If the point is just to know if the assignment went through, then you can check if(c == MySingleton.Instance), that'd tell you if the singleton points to that instance object. I feel the problem is more in the design of the OP. – Everts Dec 01 '18 at 10:07
  • A better question is [why would you use a singleton at all?](https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern) – John Wu Dec 01 '18 at 12:53
  • I am using Unity, and had some problems with constructors for a long time. If I remember, they were called at various inconvenient times during editor, so after countless hours of hacking I moved code to other Runtime-only init functions. It was all about initialization, and the order of many script initializations that had to be spaced out over at least 2 frames. Perhaps there was something else that don't remember. – Kari Dec 01 '18 at 13:08