I have many classes in an assembly that I can't or don't want to modify. At some point of runtime, I want to know which of them have already been "initialized": static initializer (= static constructor) has run.
Is there a way to do it with reflection or something else?
For information, not every class in an assembly is initialized when the assembly is loaded. This can be easily observed with this piece of code:
public static class Foo
{
static Foo() { MainClass.Value = "Something"; }
public static void DoSomething() { Thread.Sleep(100); }
}
public static class MainClass
{
public static string Value = "Nothing";
public static void Main()
{
Console.WriteLine(Value);
Foo.DoSomething();
Console.WriteLine(Value);
}
}
Displays:
Nothing
Something
As said HimBromBeere, and as confirmed in this article,
A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
So you need to use your class once, a property, a method, whatever, to initialize it... You have no control on it, you can't call it programatically and, if you want to know if the static constructor has been used, you'll use the class, so it could be called at this point...
As said Rango, you can use a flag in your constructor, if you really absolutly need to know...
Related
In .Net does static class internally create one object or does it not create any object at all. As per Microsoft docs
As is the case with all class types, the type information for a static class is loaded by the .NET Framework common language runtime (CLR) when the program that references the class is loaded. The program cannot specify exactly when the class is loaded. However, it is guaranteed to be loaded and to have its fields initialized and its static constructor called before the class is referenced for the first time in your program. A static constructor is only called one time, and a static class remains in memory for the lifetime of the application domain in which your program resides.
Can we say an object is created implicitly here.? I'm sure that simply writing static class won't create memory for it until static class or any of its members are referenced some where in code. Correct me if i'am wrong.
If I understood your question correctly, you are interested if the static class object is initialized if you don't call it from anywhere in the code.
So, I just created simple console application with static class, and put some Console.WriteLine commands in the constructor like this:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
static class SomeClass
{
static SomeClass()
{
Console.WriteLine(GetId(1));
Console.WriteLine(GetId(2));
}
public static string GetId(int Id) { return Id.ToString(); }
}
I got the following output:
Hello World!
Then I run the program with the access to the static class:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.WriteLine(SomeClass.GetId(3));
}
}
static class SomeClass
{
static SomeClass()
{
Console.WriteLine(GetId(1));
Console.WriteLine(GetId(2));
}
public static string GetId(int Id) { return Id.ToString(); }
}
And here, my console output was:
Hello World!
1
2
3
Which means that if you don't call the class inside your program, it is not being initialized and the object is not created accordingly.
But if you access the class, the object is created before it's accessed first time in the code, that means that constructor creates it when it's first called, without separate initialization, like: var _someClass = new SomeClass();, it is created before first access, and is created only once during the lifetime of your program, and no matter how much times you call it in your code, after first initialization, the instance lives until your software is running, as no matter how much times or where I would use functions or properties from this SomeClass across the program, I would be reusing the same instance, and if you don't call the class within your code, instance is not created at all, and that's what Microsoft docs refer to I suppose.
In Obj-c there is the static Initialize method which is called the first time that class is used, be it statically or by an instance. Anything like that in C#?
You can write a static constructor with the same syntax as a normal constructor, except with the static modifier (and no access modifiers):
public class Foo {
static Foo() {
// Code here
}
}
Usually you don't need to do this, however - static constructors are there for initialization, which is normally fine to do just in static field initializers:
public class Foo {
private static readonly SomeType SomeField = ...;
}
If you're using a static constructor to do more than initialize static fields, that's usually a design smell - but not always.
Note that the presence of a static constructor subtly affects the timing of type initialization, requiring it to be executed just prior to the first use - either when the first static member access, or before the first instance is created, whichever happens first.
There is a static constructor. As per msdn:
A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced.
public class Foo
{
static Foo() {} //static constructor
}
Yes, it is called a constructor.
By MSDN:
public class Taxi
{
public bool isInitialized;
//This is the normal constructor, which is invoked upon creation.
public Taxi()
{
//All the code in here will be called whenever a new class
//is created.
isInitialized = true;
}
//This is the static constructor, which is invoked before initializing any Taxi class
static Taxi()
{
Console.WriteLine("Invoked static constructor");
}
}
class TestTaxi
{
static void Main()
{
Taxi t = new Taxi(); //Create a new Taxi, therefore call the normal constructor
Console.WriteLine(t.isInitialized);
}
}
//Output:
//Invoked static constructor
//true
Consider this example code:
public class A<T>
{
public static T TheT { get; set; }
}
public class B : A<string>
{
static B() {
TheT = "Test";
}
}
public class Program {
public static void Main(String[] args) {
Console.WriteLine(B.TheT);
}
}
Here B.TheT is null. However, changing the Main method like this:
public static void Main() {
new B();
Console.WriteLine(B.TheT);
}
B.TheT is "Test", as expected. I can understand that this forces the static constructor to run, but why does this not happen for the first case?
I tried reading the spec, and this caught my attention (§10.12):
[...] The execution of a static constructor is triggered by the first of the
following events to occur within an application domain:
• [...]
• Any of the static members of the class type are referenced.
My interpretation of this is that since TheT is not a member of B, the static constructor of B is not forced to be run. Is this correct?
If that is correct, how would I best let B specify how to initialize TheT?
A.TheT is "Test", as expected. I can understand that this forces the static constructor to run, but why does this not happen for the first case?
Basically, you haven't really referenced B. If you look in the IL, I think you'll find that your code was actually equivalent to:
public static void Main(String[] args) {
Console.WriteLine(A<string>.TheT);
}
The compiler worked out that that's really the member you meant, even though you wrote B.TheT.
If that is correct, how would I best let A specify how to initialize TheT?
I would try to avoid doing this to start with, to be honest... but you could always just add a static method to B:
public static void Initialize() {
// Type initializer will be executed now.
}
Static constructor is called before the first access or at the latest when the first access is made. I.e you know it has been called when first access is made but not how long before. However, if no access is made it won't be called. So you cannot control when only if it s called.
As per MSDN reference
A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced.
In second case called static contructor and it will call the actual types' static contructor, and not that one of derived one. So in your case it calls the static ctor of the A<T> =>A<string> and not of A.
To prove this behaviour just do the following:
public class Base {
static Base() {
"Base static".Dump();
}
}
public class Derived : Base {
static Derived() {
"Derived static".Dump();
}
public static string temp = "Hello";
}
and call
Derived.temp.Dump();
You will get:
Derived static
Hello
This is what you actually do in your code, you acess derived type A<string> and it's default static ctor is called.
I stumbled upon a problem where i need an instance of the class inside its static constructor. I believed it was not possible to do it so i tried the following:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Foo.someString);
Console.ReadLine();
}
}
class Foo
{
public static readonly string someString;
static Foo()
{
someString = new Foo().CreateString();
}
private string CreateString()
{
return "some text";
}
}
To my surprise, it works - the output is "some text". I believed the static constructor must run and complete before instances of the class can be created. This answer shows that this is not necessarily the case. Does this mean that static and instance constructors are independent of each other? And finally, is it safe to do this (create instances in static constructor)?
p.s. Let's ignore the fact that this can be avoided by using a different approach.
All that the specification says is that the static constructor will be called before any instance of the class is created. But it doesn't state anything about the fact that this constructor must finish:
A static constructor is used to initialize any static data, or to
perform a particular action that needs to be performed once only. It
is called automatically before the first instance is created or any
static members are referenced.
You could perfectly fine create instances of the class inside the static constructor and this is safe.
It is safe as it will be called only once.
Static constructor called automatically before the first instance is created or any static members are referenced any static fields are referenced. Hence when your application ran and you accessed Foo, the static constructor was executed and your string was initialized.
Is it safe ? : As such there is no harm in doing this. It is just they are executed only once.
For information on this read Static Classes and Static Class Members on MSDN
So here is what I'm thinking...
public class MyClass
{
public const string MyConstant = "MyConstantValue";
private static MyClass DefaultInstance;
static MyClass()
{
DefaultInstance = new MyClass();
}
}
...
NotificationService.RegisterForNotification(MyClass.MyConstant, Callback);
Will this work or do I need to use something like a static readonly property field to trigger the static constructor?
Use of a constant doesn't necessarily result in a member access which would cause the static constructor to be called. The compiler is allowed to (encouraged, even) substitute the value of the constant at compile time.
Your suggested workaround of static readonly should be ok, although readonly suggests a field, not a property. Properties are read-only when they have no setter, the readonly keyword isn't involved.
A simple example:
class HasSConstructor
{
internal const int Answer = 42;
static HasSConstructor()
{
System.Console.WriteLine("static constructor running");
}
}
public class Program
{
public static void Main()
{
System.Console.WriteLine("The answer is " + HasSConstructor.Answer.ToString());
}
}
Output under .NET 4.0:
The answer is 42
The static constructor never runs!
Static constructor is called automatically before the first instance is created or any static members are referenced. See here: MSDN: Static Constructors
By the way, constant fields are inherently static, but as pointed they may (and probably will) be substituted by the value itself.
The static constructor will not be called if you're just accessing public constants. For example, consider this class:
class Testo
{
public const string MyValue = "Hello, world";
public static readonly int xyzzy;
static Testo()
{
Console.WriteLine("In static constructor");
xyzzy = 27;
}
}
Now, in another class, execute:
Console.WriteLine(Testo.MyValue);
Console.WriteLine(Testo.xyzzy);
Your output will be:
Hello, world
In static constructor
27
Constants are hoisted from the class at compile time. So the value of Testo.MyValue does not reference the Testo class at runtime. The static constructor is not called until you call something that requires initialization.
So, yes, you need to access something like a static readonly if you want to ensure that the constructor is called.
No, you don't need such. Static constructor is called when the class is loaded.