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.
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
};
}
}
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
I want to get the Lazy instance in another class the problem is that the T type is only set in the main class
the first class where the instance is is this:
public class singleton<T> where T : class, new()
{
private readonly static Lazy<T> val = new Lazy<T>(() => new T());
public static T instance { get { return val.Value; } }
public int UserID {get;set;}
}
now I have a other class for all user datas
public class User
{
public string Name()
{
return data.GetUserFromID(singleton.instance.UserID)
}
}
the singleton is not working because I need the Argument but the T is only in the main class
public class main : singleton<main>
{
public main()
{
UserID = 5;
}
}
EDIT
how do I get the ID from the singleton class inside another class like this
singleton file
public class singleton<T> where T : class, new()
{
private readonly static Lazy<T> val = new Lazy<T>(() => new T());
public static T instance { get { return val.Value; } }
public int UserID {get;set;}
private singleton() {
Datas.UserID = UserID;
}
}
another file
public class Datas {
public static int UserID {get;set;}
}
the singleton is not working because I need the Argument but the T is only in the main class
All you need do is change your code from:
public class User {
public string Name() {
return data.GetUserFromID(singleton.instance.UserID)
}
}
...to specifying the generic type argument:
public class User
{
public string Name()
{
var m = singleton<main>.instance;
Console.WriteLine($"Inside User.Name, m.UserId = {m.UserID}");
return "todo";
}
}
This is required because your client code is accessing the generic base directly. Had you encapsulated it into a factory manager or similar, clients would not need to specify the type.
Here is a little test harness
private void Run()
{
var x = singleton<main>.instance;
Console.WriteLine($"x.UserId = {x.UserID}");
var y = singleton<main>.instance;
Console.WriteLine($"y.UserId = {y.UserID}");
x.UserID++;
Console.WriteLine($"x.UserId = {x.UserID}");
Console.WriteLine($"y.UserId = {y.UserID}");
var user = new User();
Console.WriteLine($"User.Name = {user.Name()}");
var mp = MissPiggy.Instance;
}
Which produces the following results. Note how changing properies on two different variables modifies the same singleton.
There are a few problems too with how you are implementing singletons. A singleton class should have a private constructor and it should be the one managing lifetimes and not a secondary class.
e.g.
public sealed class MissPiggy
{
private static Lazy<MissPiggy> _instance = new Lazy<MissPiggy>(() => new MissPiggy());
private MissPiggy()
{
}
public static MissPiggy Instance
{
get { return _instance.Value; }
}
}
singleton<t> is a generic type - you can't refer to it without a generic type parameter.
Under the hood, it's actually generating new types.
So when you do this:
var mainSingleton = singleton<main>.instance;
It's actually creating a new type which looks like this:
public class NewGenericTypeWithWeirdName
{
private readonly static Lazy<main> val = new Lazy<main>(() => new main());
public static main instance { get { return val.Value; } }
public int UserID { get; set; }
}
...and if you declare var otherSingleton = singleton<SomethingElse>.instance; then it does the same thing - it creates another type, just like above, except T is replaced with SomethingElse.
That's why you can't do this:
singleton.instance.UserID
Because the compiler doesn't know which type you're referring to. Is it the type it generated for singleton<main>, or is it the type generated for singleton<SomethingElse>? They're actually different types, which means the static properties - including UserID, will be different for each of them.
You could do this:
return data.GetUserFromID(singleton<main>.instance.UserID);
^^^^^^
...because now you're telling it the actual type - it's singleton<main>.
Just to clarify, unless the class has a private constructor and no non-private constructors, it isn't a singleton.
You can do this:
var mainSingleton = singleton<main>.instance;
and it will always return the same instance of main.
But you can also do this:
var m1 = new singleton<main>();
var m2 = new singleton<main>();
You can create multiple instances, so it's not a singleton. To fix this, add a private constructor to singleton:
private singleton() {}
Now the constructor can only be called from within the class. That means the only way to get an instance is to call instance. Every time you do that you'll get the same instance, so now it really is a singleton.
I have two classes that I'm trying to use to implement a string enumeration pattern. The problem is the static constructor for the child class isn't being called when an operator of the parent class is called. Is there a way I can fix that without adding a hack to the code to initialize the static members?
public abstract class BaseStringEnum<T> where T : BaseStringEnum<T>
{
public string Value { get; private set; }
private static List<T> _values = null;
protected static List<T> Values
{
get
{
if (_values == null)
{
_values = new List<T>();
}
return _values;
}
}
protected BaseStringEnum(string value, string resId)
{
Value = value;
ResourceId = resId;
Values.Add((T)this);
}
public static implicit operator string(BaseStringEnum<T> value)
{
return value.Value;
}
public static implicit operator BaseStringEnum<T>(string value)
{
return Values.Where(v => v.Value.Trim() == value.Trim()).First();
}
}
public sealed class UseTimeStringEnum : BaseStringEnum<UseTimeStringEnum>
{
private UseTimeStringEnum(string value, string resourceId) : base(value, resourceId) { }
public static readonly UseTimeStringEnum None;// = new UseTimeStringEnum("N", "None");
public static readonly UseTimeStringEnum Required;// = new UseTimeStringEnum("R", "Required");
public static readonly UseTimeStringEnum Optional;// = new UseTimeStringEnum("O", "Optional");
static UseTimeStringEnum()
{
None = new UseTimeStringEnum("N", "None");
Required = new UseTimeStringEnum("R", "Required");
Optional = new UseTimeStringEnum("O", "Optional");
}
}
The problem is when the code tries to do something like (UseTimeStringEnum)"R" it fails because the static constructor hasn't fired yet. I feel like it should fire because I'm using a static operator.
Static constructor of some class is called once one of the following conditions is met:
Instance of the class is created;
any static field of the class is accessed.
Since you do not create instances of UseTimeStringEnum neither acess it's static fields within your code, the static constructor is not called.
So the point is: BaseStringEnum does not know of UseTimeStringEnum at the compile time.
I see the only proper solution - we can refer UseTimeStringEnum at the runtime.
I added static constructor to the BaseStringEnum class wich loads and observes all available subclasses with Reflection.
now the static constructor is called.
EDIT: Mykroft pointed there is the way to call a static constructor directly instead of referencing static fields with reflection. So i believe the final code snippet should be
static BaseStringEnum()
{
var StringEnumTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(type => type.IsSubclassOf(typeof(BaseStringEnum<T>)));
foreach (var type in StringEnumTypes) type.TypeInitializer.Invoke(null, null);
}
As others rightly pointed out my constructor isn't being called because the parent class doesn't know the child class. Fortunately in this SO question I found a snippet of code that calls the constructor explicitly.
typeof(T).TypeInitializer.Invoke(null, null);
This works for my purposes here.
I found out about properties a couple of days ago(not sure if I understood how to use them very well). So I decided to make some tests.
so here's what Ive done :
I created a class that contains some properties such as :
public string _string1 { get; set; }
public string _string2 { get; set; }
and then I created a method in the same class lets say like this :
public static string Example()
{
switch(_string1.length > _string2.length)
{
case true :
return _string1;
break;
default : return _string2;
}
}
just a stupid example to understand a bit
and then I called the method from the main class after that I got a couple of errors :
An object reference is required for the non-static field, method, or property 'xxx.properties._string1.get'
Well its certainly a stupid mistake but I'm new to c# and I could use some assistance.
You need to make your properties static too:
public static string _string1 { get; set; }
public static string _string2 { get; set; }
Essentially a static method has no state. Those fields when declared in a non-static manner are essentially like a state, therefore it can't access them. By marking them static you say this is the Global value for the AppDomain.
One thing to be wary of using static fields like this however is if you start using any sort of threading and try to store state then you can end up with nasty issues to debug because you've no idea what state you're shared resources are in.
A way to protect against this (if you don't need state) is to define these as constants fields instead. Then you can't modify them, but means you need not worry about someone changing them when you didn't expect it.
public const string _string1;
public const string _string2;
A static method can always access other static members only. Now since your properties are not static hence your static method cannot access/manipulate them.
You can make these fields as static and then the error will go away. Once these are static no object reference would be required to access them.
They can then be simply accessed through the classname itself.
for example
public class YourClass
{
public static string _string1 { get; set; }
public static string _string2 { get; set; }
public static string Example()
{
switch(_string1.length > _string2.length)
{
case true :
return _string1;
break;
default : return _string2;
}
}
}
Now in your program:
YourClass._string1="some string"; // You can access the static properties with class name
YourClass._string2="some other string";
YourClass.Example() // You can call the static function with class name.
It's all about instance versus static scope. Whilst the examples above make your error go away, it is important to understand when to use static methods, variables, properties versus instance ones. In fact, you could say that using static members is not really a pure OOP practice. Most of the time, static members are misused because people misunderstand these OOP basics.
Static methods and variables are shared amongst all object instances for your class. Therefore, in most scenarios, you will need to have a specific requirement to have a static method/variable, such as keeping a total count of objects in a static variable which would be accessible across all your object instances.
You can create a new instance of the class where variables are.
public class YourClass
{
public string _string1 { get; set; }
public string _string2 { get; set; }
...
}
public static string Example()
{
YourClass yourClass = new YourClass();
switch(_string1.length > _string2.length)
{
case true :
return yourClass._string1;
break;
default : return yourClass._string2;
}
}
So I have a static class with a list declared as one of it's members, and I populate the list in a function lets say it's called PopulateList(). Is it possible to modify the list in another function without:
1) Calling it as a parameter
2) Instantiating it in a constructer (Trying to keep the class static. I'm working off of a template so I can't really change the structure of the classes)
Without somehow instantiating though, I will obviously receive null exceptions, so I was wondering if there is a 3rd way to do this.
public Static class MyClass{
static public List<String> m_SuiteFileNameList2=null;
public static bool Function1(inp){
//m_SuiteFileNameList2 stuff
}
public static void Function2(){
//m_SuiteFileNameList2 other stuff
}
}
You can either use a static constructor, or static initialization. It will allow you to keep your class static, but will ensure that the list is always defined:
static class MyClass
{
static MyClass()
{
MyList = new List<Whatever>();
}
// etc
}
or
static class MyClass
{
public static List<Whatever> MyList = new List<Whatever>();
}
Another option is to add a null check to every usage of the list:
public static void MyMethod()
{
if (MyList == null)
{
MyList = new List<Whatever>();
}
//etc
}
I would call a function called 'Initialize' which is static and takes care of your static members.
Though I would recommend against static members if possible.
Why?
They can lead to head aches (yes, that hurts)
Their behaviour in memory allocation is different (How is memory allocated for a static variable?)
code snippet
public static class YourClass
{
public static List<string> YourList;
public static void InitializeList()
{
YourList = new List<string>();
YourList.Add("hello");
YourList.Add("how");
YourList.Add("are");
YourList.Add("you?");
}
}
Call your Initialize-Function from outside:
YourClass.InitializeList();
EDIT: Given your code , you can also do it this way:
public Static class MyClass{
static public List<String> m_SuiteFileNameList2=null;
public static bool Function1(inp){
if(m_SuiteFileNameList2 == null)
{ m_SuiteFileNameList2 = new List<String>();}
//m_SuiteFileNameList2 stuff
}
public static void Function2(){
if(m_SuiteFileNameList2 == null)
{ m_SuiteFileNameList2 = new List<String>();}
//m_SuiteFileNameList2 other stuff
}
}
I want to have a class like:
public class Forest<S, T>
{
static IList<Animal> coolGuys = new List<Animal>();
}
But I want coolGuys to be really static, which means it has to be unique through the entire lifetime of the application. And right now its not. MS discourages this pattern, ReSharper warns, but how does one really achieve what I want?
May be I will have to do more work by creating another static class and have a public static field there or a public instance field in another singleton class. Its ok to have a redundant public class to hold just a static field, but the thing I want to avoid is the field being public/internal. I mean coolGuys is just meant for Forest<,>, why expose the incoherent things to outside world.
public class Forest
{
public static IList<Animal> coolGuys = new List<Animal>(); //want to avoid
}
public class Forest<S, T>
{
Forest.coolGuys.Add(cutie);
}
Any better pattern?
Approach 1 - Inject a State Provider
Create a type to store data.
Abstract it with an interface, so you can inject a different provider if desired (e.g. for testing).
Consuming class doesn't care about the implementation, other than it guarantees statefulness.
Concurrent dictionary takes care of thread safety.
public interface IStateProvider
{
void Store( string key, object value );
object Get( string key );
}
public class StateProvider : IStateProvider
{
private static ConcurrentDictionary<string, object> _storage = new ConcurrentDictionary<string, object>();
public void Store( string key, object value )
{
// add to storage
}
public object Get( string key )
{
// get from storage
}
}
public class Forest<T1, T2>
{
private IStateProvider _stateProvider;
public Forest( IStateProvider stateProvider )
{
_stateProvider = stateProvider;
}
public void Foo()
{
// do something with the stateful value
}
}
// of course, you could do this with a DI framework
var stateProvider = new StateProvider();
var forest = new Forest<Foo, Bar>( stateProvider );
Approach 2 - Base Class
This approach is less elegant but a bit more straightforward.
public abstract class ForestBase
{
private static List<object> _staticList = new List<object>();
protected List<object> StaticList
{
get { return _staticList; }
}
}
public class Forest<T1, T2> : ForestBase
{
public void Foo()
{
StaticList.Add( 12345 );
}
}
This hides internal data and should give you only one single instance of the static list, versus one instance per combination of generic arguments.