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.
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.
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.
}
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 have two classes Class A and ClassB:
static class ClassA
{
static string SomeMethod()
{
return "I am a Static Method";
}
}
class ClassB
{
static string SomeMethod()
{
return "I am a Static Method";
}
}
I want to know what is the difference between ClassA.SomeMethod(); and ClassB.SomeMethod();
When they both can be accessed without creating an instance of the class, why do we need to create a static class instead of just using a non static class and declaring the methods as static?
The only difference is that static methods in a nonstatic class cannot be extension methods.
In other words, this is invalid:
class Test
{
static void getCount(this ICollection<int> collection)
{ return collection.Count; }
}
whereas this is valid:
static class Test
{
static void getCount(this ICollection<int> collection)
{ return collection.Count; }
}
A static class can only contain static members.
A static method ensures that, even if you were to create multiple classB objects, they would only utilize a single, shared SomeMethod function.
Technically, there's no difference, except that ClassA's SomeMethod must be static.
If you have a non-static class containing only static methods, you could create an instance of that class. But you can't use that instance meaningfully. NB: when you don't define a constructor, the compiler adds one for you.
A static class does not have a constructor, so you can't create an instance of it. Also the compiler gives an error when you add an instance method to it (where you meant a static method).
See also docs.
A static method belongs to the class and a non-static method belongs to an object of a class. That is, a non-static method can only be called on an object of a class that it belongs to. A static method can access only static members. A non-static method can access both static and non-static members because at the time when the static method is called, the class might not be instantiated (if it is called on the class itself). In the other case, a non-static method can only be called when the class has already been instantiated. A static method is shared by all instances of the class. Whenever a method is called in C++/Java/C#, an implicit argument (the ‘this’ reference) is passed along with/without the other parameters. In case of a static method call, the ‘this’ reference is not passed as static methods belong to a class and hence do not have the ‘this’ reference.