Let's have two code snippets:
A:
public class Foo
{
private static Bar _unused = new Bar();
}
B:
public class Foo
{
private static Bar _unused;
static Foo()
{
_unused = new Bar();
}
}
In case A the CLR will not even call the Bar ctor (unless it is debug build or the debugger is attached), however in case B it is called under all circumstances.
The thing is that in Bar constructor one can have calls that will make this instance reachable from elsewhere - most typically events subscriptions.
So:
Why are the cases A and B evaluated differently?
Why the CLR is not calling Bar ctor at all in case A - as it
should not evaluate it as garbage until ctor is finished and instance
is assigned to the appropriate field?
If you don't create a constructor:
The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.
If you do have a static constructor:
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.
Related
According to the docs:
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.
But i saw in stackoverflow post, the following quote from the C# specification:
If a static constructor (§10.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor.
It's contradicting, i don't understand what come first, the static constructor or the static member initialization.
Consider this class:
public static class TestStatic
{
public static int SomeValue = GetValue();
static TestStatic()
{
Console.WriteLine("Constructor");
}
}
And this supporting method:
public static int GetValue()
{
Console.WriteLine("GetValue");
return 5;
}
If you run this code:
Console.WriteLine(TestStatic.SomeValue);
The output you will get is:
GetValue
Constructor
5
So you can see that both of the statements you posted are correct. The constructor is called before the static member (SomeValue) is referenced and the static field initialiser is called before the constructor.
Both of the statements you have mentioned are true and are in sync with each other. I am not sure why you think they are contradicting.
The order of execution is as follows:
Static fields with initializers.
Static Constructor.
The above is as per your second statement. The first statement just mentions when these actions are performed i.e. before:
The first instance of the class is created.
Any static members are referenced.
In fact, the above conditions can be taken as guaranteed for static constructors that the static field initializers will be executed and static constructor will be called before any of the two happens (statement 1).
The C# specification clearly mentions:
The static constructor for a class executes at most once in a given
application domain. The execution of a static constructor is triggered
by the first of the following events to occur within an application
domain: An instance of the class is created. Any of the static members
of the class are referenced. If a class contains the Main method
(Section 3.1) in which execution begins, the static constructor for
that class executes before the Main method is called. If a class
contains any static fields with initializers, those initializers are
executed in textual order immediately prior to executing the static
constructor.
Just to add on, since you have highlighted -
before the first instance is created or any static members are referenced.
This just means that it is possible to refer to a static member of a class even before creating an instance of that class. So, even in that case, the static constructor will be called before accessing the static member.
If you see DavidG's code in his answer, even though the class is not being instantiated, but one of the static members is being referenced, still the static field initialization takes place before that which is followed by static constructor execution.
Example:
public static class Test
{
public static int i = 10;
public static int j = new Func<int>(() => {
Console.WriteLine("Static field initializer called."); return 20;
})();
static Test()
{
Console.WriteLine("Static Constructor called.");
}
}
Now if you execute:
Console.WriteLine(Test.i);
You get the following output:
Static field initializer called.
Static Constructor called.
10
The reason for such a behavior (and it's by design) is that the initialization of static fields actually happens as part of the static constructor. The compiler prepends the static constructor logic with all the expressions you have for static fields' initializers.
Env.: C#6, Visual Studio 2015 CTP 6
Given the following example:
namespace StaticCTOR
{
struct SavingsAccount
{
// static members
public static double currInterestRate = 0.04;
static SavingsAccount()
{
currInterestRate = 0.06;
Console.WriteLine("static ctor of SavingsAccount");
}
//
public double Balance;
}
class Program
{
static void Main(string[] args)
{
SavingsAccount s1 = new SavingsAccount();
s1.Balance = 10000;
Console.WriteLine("The balance of my account is \{s1.Balance}");
Console.ReadKey();
}
}
}
The static ctor is not being executed for some reason. If I declare SavingsAccount as a class instead of a struct, it works just fine.
The static constructor isn't executed because you are not using any static members of the struct.
If you use the static member currInterestRate, then the static constructor is called first:
Console.WriteLine(SavingsAccount.currInterestRate);
Output:
static ctor of SavingsAccount
0,06
When you are using a class, the static constructor will be called before the instance is created. Calling a constructor for a structure doesn't create an instance, so it doesn't trigger the static constructor.
According to the CLI spec:
If not marked BeforeFieldInit then that type’s initializer method is
executed at (i.e., is triggered by):
first access to any static field of that type, or
first invocation of any static method of that type, or
first invocation of any instance or virtual method of that type if it is a value type or
first invocation of any constructor for that type
For structs which have an implicit default constructor it is not actually invoked, so you can create an instance and access its fields. Everything else (invoking custom constructors, instance property access, method calls, static field access) will trigger static constructor invocation.
Also note that invoking inherited Object methods which are not overridden in the struct (e.g. ToString()) will not trigger static constructor invocation.
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
The MSDN RyuJIT blog entry gives this instruction for setting up CTP3:
Tricky thing necessary until RyuJIT is final: Add a reference to
Microsoft.Numerics.Vectors.Vector to a class constructor that will
be invoked BEFORE your methods that use the new Vector types. I’d
suggest just putting it in your program’s entry class’s constructor.
It must occur in the class constructor, not the instance constructor.
I'm far better versed in class/instance construction in Objective-C than I am in C#. Is he talking about a different concept? What is the difference between a class constructor and an instance constructor in C#? Is the "class constructor" in this case simply the parameterless constructor?
I think this refers to the static constructor
Class constructor = Static constructor
Instance constructor = Normal constructor
For example,
class MyClass
{
// Static/Class constructor.
// Note: Static constructors cannot have visibility modifier (eg. public/private),
// and cannot have any arguments.
static MyClass()
{
... // This will only execute once - when this class is first accessed.
}
// Normal/Instance Constructor.
public MyClass(...)
{
... // This will execute each time an object of this class is created.
}
}
So as an example, consider the following code:
static void Main(string[] args)
{
var a = new MyClass(); // Calls static constructor, then normal constructor.
a.DoSomething();
var b = new MyClass(); // Calls normal constructor only.
b.DoSomething();
}
Also, consider the following code:
static void Main(string[] args)
{
MyClass.SomeStaticMethod(); // Calls static constructor, then SomeStaticMethod().
MyClass.SomeOtherStaticMethod(); // Calls SomeOtherStaticMethod() only.
// Note: None of the above calls the normal constructor.
}
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