Home > Net >  Is "this" static? Checking for Static in the constructor
Is "this" static? Checking for Static in the constructor

Time:06-16

I need to determine if a member T of class T is a static member, in the constructor. I expect this will involve checking some attributes of "this", but I haven't been able to determine what to look for.

public class Thing
{
    public static readonly List<Thing> ListOfStaticThings = new();
    public static readonly Thing StaticThing1 = new ("StaticThing1");
    public static readonly Thing StaticThing2 = new ("StaticThing2");
    public static readonly Thing StaticThing3 = new ("StaticThing3");
    public Thing NonStaticThing = new("NonStaticThing");
    public string Name { get; set; }
    private Thing(string name) 
    {
        Name = name;
        if(this.IsStatic)  //how to determine if the thing being constructed is static?
        { ListOfStaticThings.Add(this);}
    }

}

How do I identify if the Static attribute is applied to this?

*** UPDATED ***

In this example, both StaticThing and NonStaticThing will be constructed using the private constructor. However, only the StaticThing should be added to the ListOfStaticThings when constructed. The full implementation will have 20 static readonly fields of the class type.

I've already verified that the ListOfStaticThings will contain the StaticThing.

The ListOfStaticThings has multiple uses. This is on the path to Enumeration Classes, with this list containing all the possible Things (such as account statuses) permitted by the class. In addition, the ListOfStaticThings can be passed to EFCore.HasData to seed the data in the table. It can also be used for data validation in unit testing because it contains all the data and is persisted in the model.

However, all those use cases are beyond the scope of this question. The piece I'm looking for is how to identify if the "this" being constructed is static so I can add it to the ListOfStaticThings. I want StaticThing1, 2 & 3 to be in the list, but not NonStaticThing.

*** Final Update *** As pointed out by McAden's answer, this is not necessary because the non-static member of T cannot be added to class T without causing an infinite recursion overflow. Since only static members of T can be added, there is no need to determine if they are also static in the constructor.

CodePudding user response:

I think you're going about it the wrong way - all static members should be initialized either in the property itself or in a static constructor, so I would do it this way:

public class Thing
{
    public static readonly List<Thing> ListOfStaticThings;
    public static readonly Thing StaticThing1 = new Thing("StaticThing1");
    public static readonly Thing StaticThing2 = new Thing("StaticThing2");
    public static readonly Thing StaticThing3 = new Thing("StaticThing3");
    // public Thing NonStaticThing = new("NonStaticThing");
    public string Name { get; set; }
    private Thing(string name) 
    {
        Name = name;
    }
    static Thing()
    { 
        ListOfStaticThings = new List<Thing> {
            StaticThing1, 
            StaticThing2, 
            StaticThing3
        };
    }

}

Now the instance constructor doesn't need to know if it's a "static" instance or not.

However, to be safe (meaning not rely on the order of initializers), I would also crate the static instances in the static constructor:

public class Thing
{
    public static readonly List<Thing> ListOfStaticThings;
    public static readonly Thing StaticThing1;
    public static readonly Thing StaticThing2;
    public static readonly Thing StaticThing3;
    public string Name { get; set; }
    private Thing(string name) 
    {
        Name = name;
    }
    static Thing()
    { 
        ListOfStaticThings = new List<Thing> {
            StaticThing1 = new Thing("StaticThing1"), 
            StaticThing2 = new Thing("StaticThing2"), 
            StaticThing3 = new Thing("StaticThing3")
        };
    }

}

Now, if you need to know if it's "static" for some other reason, then I would create another private constructor that takes a static flag:

private Thing(string name, bool isStatic=False) : this(name) 
{
    if (isStatic) {
        // Do different stuff for a "static" instance
    }
}

but I would not put logic there to "add itself" to a static list - that can be accomplished more cleanly another way.


how [do I] prevent non-static members being added to the list

If you want to make the list immutable, then you could either expose it as an immutable type or interface like 'IEnumerable', or you could just generate the list on the fly with a static property getter:

public static IEnumerable<Thing> ListOfStaticThings {
    get {
        return new List<Thing> {
            StaticThing1, 
            StaticThing2, 
            StaticThing3
        };
    }
}

CodePudding user response:

Updated Answer:

In OP's very specific preferred approach there's no point. The public Thing NonStaticThing = new("NonStaticThing"); will result in a StackOverflowException as each child will try to create another child infinitely.

In general, however, my advice to anybody trying to do something "statically" and otherwise "not" would be to use a static constructor for static things.

Original Answer based upon un-edited question:

Order of operations - The static field will be assigned before anything else outside that class can call the constructor on that class and the constructor for setting that static readonly field will be called before the static field is actually assigned. Simply check to see if the static field is null in your constructor.

private static void Main(string[] args)
{
    var test = new Thing();
    Console.WriteLine(test.IsStaticInstance); // False
    Console.WriteLine(Thing.Instance.IsStaticInstance); // True
}

public class Thing
{
    public static readonly Thing Instance = new Thing();
    public Thing()
    {
        IsStaticInstance = Instance == null;
    }
    public bool IsStaticInstance { get; }
}
  • Related