Static initialization of inherited static member - c#

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.

Related

Static class initialization

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.

C#: determine if a class has already been initialized

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...

Why static constructor not called before first call to class method

According to Jon Skeet's artice C# and beforefieldinit and discussion in When is a static constructor called in C#? static constructor must be called before first call to a method of the class.
For some reason following code does not exhibit this behavior:
namespace AbstractAndStatic
{
class Program
{
static void Main(string[] args)
{
StaticClass.Equals(1,2);
StaticClass.foo();
}
}
static class StaticClass : Object
{
public static void foo()
{
Console.WriteLine("Static");
}
static StaticClass()
{
Console.WriteLine("static constructor");
}
}
class TestClass
{
public void deb()
{
Console.WriteLine("Test Class Debug");
}
}
}
I am debugging the above code using the Visual Studio Debugger. When the statement StaticClass.Equals(1,2); gets executed in the Main method the static Constructor is not getting called but when StaticClass.foo(); is executed it calls static constructor and then call the foo method.
I am little confused as why it didn't get called the the first time when executing StaticClass.Equals(1,2);.
Your call to StaticClass.Equals is actually just a call to Object.Equals(Object, Object), as StaticClass doesn't provide an applicable overload for Equals. If you look in the IL, you'll see that the compiler has resolved the call to just Object.Equals(1, 2). If you're not calling a method which actually involves the static class, it doesn't need to be initialized.
The execution of a static constructor is triggered by the first of the following events to occur :
An instance of the class is created.
Any of the static members of the class are referenced.

Class Initialize() in C#?

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

C#: Can a base class use a derived class's variable in a static function?

Is there anyway of having a base class use a derived class's static variable in C#? Something like this:
class Program
{
static void Main(string[] args)
{
int Result = DerivedClass.DoubleNumber();
Console.WriteLine(Result.ToString()); // Returns 0
}
}
class BaseClass
{
public static int MyNumber;
public static int DoubleNumber()
{
return (MyNumber*2);
}
}
class DerivedClass : BaseClass
{
public new static int MyNumber = 5;
}
I'm trying to have it return 10, but I'm getting 0.
Here's where I'm using this: I have a class called ProfilePictures with a static function called GetTempSavePath, which takes a user id as an argument and returns a physical path to the temp file. The path base is a static variable called TempPath. Since I'm using this class in multiple projects and they have different TempPaths, I'm creating a derived class that sets that variable to whatever the path is for the project.
See Also
Why can’t I declare C# methods virtual and static?
Apart from the fact that has already been pointed out... that static variables are tied or bound to the specific class declaring them and cannot be overridden. Overriding/Polymorphism needs instances to work.
Your problem can be solved with a change in design.
string ProfilePictures.GetTempSavePath(SomeType UserId, string sBasePath)
if it just needs these 2 variables to compute the return value, you can keep it as a utility/static method. Now you can feed in different base paths..
Now it seems from your question, that you need to use this class in multiple projects (which have fixed base paths) and kind of hardcode the base path so that you dont have to specify it for each call.
Type/Class hierarchies should be defined based on behavior and not on data. Variables can handle change in data. Hence I'd suggest holding the basepath value as a static member variable, which is initialized from a resource file (DoubleClick your project properties node > Settings > Add a new Settings file > add a new setting called BasePath - string - Application scope - VALUE=C:\Users). Now you just need to tweak the app.config file for each project, no code changes, no hardcoding and not more than one type needed.
public class PathHelper
{
static string _sBasePath;
static PathHelper()
{
_sBasePath = Properties.Settings.Default.BasePath;
}
static string GetTempSavePath(string sUserId)
{
// dummy logic to compute return value, replace to taste
return Path.Combine(_sBasePath, sUserId.Substring(0, 4));
}
}
Hope that made sense
The problem is that you're re-declaring the static variable in the derived class. The MyNumber declaration in DerivedClass hides the declaration in the base class. If you remove that declaration, then references to the "MyNumber" in derived class static functions will refer to the base class variable. Of course, if you remove the declaration then you can't use a static initializer in the derived class.
You might want to consider requiring users to instantiate an instance of ProfilePictures rather than provide a static function for GetTempSavePath. That way you could overide the GetTempSavePath method to provide the correct TempPath. Or, you could simply set the value of the static path value in your derived class constructor.
Although it is possible to use inheritance with static members, you can't relly have polymorphic behavior without a "this" pointer.
Static members are not virtual, so you can not override them.
When you call DerivedClass.DoubleNumber you are actually calling BaseClass.DoubleNumber as the DerivedClass class doesn't have that method. Also, the use of MyNumber in that method is always going to be BaseClass.MyNumber no matter how you call the method.
What you are looking for is a virtual property that you can override in a derived class. As a virtual member can not be static, you need to use an instance of the class. If it's not practical to keep a reference to the instance, you can use the singleton pattern.
This kinda works:
public class ClassA
{
protected static int num = 5;
public static int GetNum()
{
return num;
}
}
public class ClassB : ClassA
{
static ClassB()
{
num = 6;
}
}
However, note the difference when you call ClassB.GetNum() before and after instantiating one object. The static initializer doesn't run until you create at least one, so you'll get 5 if nothing has been created, and 6 if at least one object has.
Provide a virtual method that returns the class static.
class BaseClass
{
public virtual int GetMyNumber() { return MyNumber; }
}
You might want to use a virtual property instead...
Using too much of static members is also not recommended if they are going to encapsulate a logic of an entire object. For example your code can be rewritten correctly in following manner... and this is the most recommended in oops,
class Program
{
static void Main(string[] args)
{
int Result = DerivedClass.Instance.DoubleNumber();
Console.WriteLine(Result.ToString()); // Returns 0
}
}
class BaseClass
{
protected BaseClass(){} // this enforces that it can not be created
public int MyNumber;
public virtual int DoubleNumber()
{
return (MyNumber*2);
}
}
public class DerivedClass : BaseClass
{
// this also ensures that it can not be created outside
protected DerivedClass(){
MyNumber = 5;
}
// only way to access this is by Instance member...
public static DerivedClass Instance = new DerivedClass();
}
This is how we access configuration values and many other single instance static objects provided by .Net Library.

Categories

Resources