Why C# allows initializing static class variables in non-static contructor? - c#

Why C# allows initializing static class variables in non-static contructor? The static variables should only be allowed to be initialized on static constructors. Any ideas?
public class customer
{
public string Name;
public customer()
{
Name = "C1";
Console.WriteLine("creating customer " + Name);
}
}
class Program
{
public static customer cust;
public Program()
{
cust = new customer(); //Why is this allowed i.e. initialize a static variable in non-static constructor?
}
static void Main(string[] args)
{
Program program = new Program();
program = new Program();
Console.Read();
}
}

Don't look at it as initializing, look at it as setting.
If you would only like it to be initialized via a static constructor or at declaration, add the readonly keyword.
E.g.
public readonly static customer cust;
//Allowed
static Program()
{
cust = new customer();
}
//Not Allowed
public Program()
{
cust = new customer();
}

The short answer is there is no reason why not to allow this. Static variables can be reached anywhere from within the class (and outside, if they're public) and the constructor is no exception. This includes changing their value, or initializing them to a new value.
There are, in fact, several patterns that can take advantage of this behavior. For example, initializing a static object the first time a class is instantiated (perhaps for caching properties that are expensive to initialize but don't change in the future). Another use might be incrementing a counter to keep track of how many of these objects are alive.
With that said, you'd want to be aware of static objects in a class before initializing, and check to see if they're null before overwriting their values.

You can access and modify a static variable from any nonstatic function, it will just overwrite the value each time it is called. The opposite is not true, though - static functions can't access nonstatic variables.

It just means that the static variable is reset every time a new object is initialized. A bit weird, but the compiler allows it.

Related

Static variable inside class

I am much confused about static variable actually i am executing below program.
class ABC
{
public static int prop { get; set; }
const int i =5;
static int j;
public ABC()
{
prop = 8;
j = 9;
Console.WriteLine("Under ABC class's constructor.");
}
public int getValue()
{
j = 6;
prop = 89;
return j;
}
}
class Program
{
static void Main(string[] args)
{
ABC obj = new ABC();
Console.WriteLine(obj.getValue());
//Console.WriteLine(ABC.j);
Console.ReadLine();
}
}
And its executing without any compile or run time error.
I have following confusions.
can we assign static variable/property inside the non static constructor?
can we assign static variable/property inside the instance method also?
If we can do assignment in above two cases for static variable/property then what is the use of static constructor?
Finally what are the locations inside a class where we can assign/initialize a static variable/property?
can we assign static variable/property inside the non static
constructor?
Yes.
can we assign static variable/property inside the instance method
also?
Yes.
If we can do assignment in above two cases for static
variable/property then what is the use of static constructor?
A static constructor is also called a type initializer. It is responsible for initializing the type it is defined in. You may use it to perform calculations that can be done upfront and are the same for all instances of that type. You'll therefore save some execution time when creating an instance because the calculation has already been done by the type initializer. Note that the type initializer runs before the type is used the first time. So you cannot deterministically tell when it actually runs. You can also not catch exceptions thrown by it because you don't actually invoke the type initializer yourself. You therefore need to be careful not to put error prone operations inside type initializers (f.e. do not do IO operations inside them).
Finally what are the locations inside a class where we can
assign/initialize a static variable/property?
From anywhere. Note that, even across threads, you can read and write to a static member from anywhere. This makes it very hard to find bugs that may occure due to a programm mutation a static somewhere in memory.
As a side note: Try to avoid having mutable static memory to keep your application simpler. If you really need to ... you should consider locking access to the static resource to prevent data races.

Static variable initialization using new gives a code hazard

I am working on some code which is something like this:
class A
{
static SomeClass a = new Someclass("asfae");
}
Someclass contains the required constructor.
The code for this compiles fine without any warning. But I get a code hazard in system:
"The Someclass ctor has been called from static constructor and/or
static initialiser"
This code hazard part of system just to make it better by warning about possible flaws in the system or if system can get into bad state because of this.
I read somewhere on the web that static constructor/initialiser can get into deadlock in c# if they wait for a thread to finish. Does that have something to do with this?
I need to get rid of this warning how can i do this.
I can't make the member unstatic as it's used by a static function.
What should I do in this case , Need help.
You could hide it behind a property and initialize it on first use (not thread-safe);
class A
{
static SomeClass aField;
static SomeClass aProperty
{
get
{
if (aField == null) { aField = new Someclass("asfae"); }
return aField;
}
}
}
or use Lazy (thread-safe):
class A
{
static Lazy<SomeClass> a = new Lazy<SomeClass>(() => new Someclass("asfae"));
}
...or this very verbose thread safe version :)
class A
{
static SomeClass aField;
static object aFieldLock = new object();
static SomeClass aProperty
{
get
{
lock (aFieldLock)
{
if (aField == null) { aField = new Someclass("asfae"); }
return aField;
}
}
}
}
By initialising it as a static field, it behaves as it would in a static constructor, i.e. it probably gets initialised the first time an instance of your class is instantiated, but might happen earlier. If you want more control over exactly when the field is initialised, you could use Lazy<T>, e.g.:
{
static Lazy<SomeClass> a = new Lazy<SomeClass>(() => new Someclass("asfae"));
}
This way, you know that the initialisation of SomeClass will only happen the first time the field is accessed and its Value property called.
I think to understand your problem you need to know the difference between static constructors and type initializers, there is a great article from Jon Skeet about this issue:
http://csharpindepth.com/Articles/General/Beforefieldinit.aspx
The point is that following constructions are not the same, and there are difference in the behavior:
class Test
{
static object o = new object();
}
class Test
{
static object o;
static Test()
{
o = new object();
}
}
In any case, you could try to create a static constructor for your class to be able to have more control on this initialization, and maybe the warning will disappear.
If the member is only used by a static method, and only by this one, I would recommend you to put it in the scope if this static method and not as class member.

Prevent a Class having static instances of it created in C#

Is there anyway way to prevent a class having static instances of it created in C#. I don't think there is but it could be useful. E.g just some attribute to prevent it.
something like this
[NoStaticInstances]
public class MyClass {
}
so that
public static MyClass _myClass;
would cause an error?
There's no such thing as a "static instance" - there's only a static variable, which is assigned a value. And there's no way of preventing static variables of a particular type being declared, unless you make the type itself static, which will prevent any instances being created and any variables of that type from being declared.
Imagine if your desired feature did exist... how would you expect the following code to behave?
class Test
{
static object foo;
static void Main()
{
MyClass bar = new MyClass();
foo = bar;
}
}
Which line of that would cause an error, if any? If it's the assignment, imagine this instead:
class Test
{
static object foo;
static void Main()
{
MyClass bar = new MyClass();
object tmp = bar;
foo = tmp;
}
}
In short, I don't think you're going to be able to prevent static variables holding references to instances of your class. Out of interest, why do you want to?
What you can do is the following:
public class MyClass
{
public MyClass()
{
#if DEBUG // Only run in debug mode, because of performance.
StackTrace trace = new StackTrace();
var callingMethod = trace.GetFrames()[1].GetMethod();
if (callingMethod.IsStatic &&
callingMethod.Name == ".cctor")
{
throw new InvalidOperationException(
"You naughty boy!");
}
#endif
}
}
Static fields will 'normally' be created by static constructors. What the above code does is looking at the calling method to see if it is a static constructor and if that's the case, throw an exception.
Note however, that this check is quite fragile and smart users can easily work around this by refactoring the creation of this method to another method. In other words, I agree with every body else that there is no good way to do this.
Such a restriction would not make sense.
What if you write
static object something = new YourClass();
Not really, there is no language or compiler feature that supports this.
No, there's no way to dictate the scope or lifetime of object references in C#.

When do static fields come into existence?

I'm trying to understand when exactly static fields come into existence and have been reading this MSDN article - http://msdn.microsoft.com/en-us/library/79b3xss3 - but it seems to contradict itself:
First it says:
Static members are initialized before the static member is accessed for the first time and before the static constructor, if there is one, is called.
But then it goes on to say:
If your class contains static fields, provide a static constructor that initializes them when the class is loaded.
So, my question is basically this: When are static fields actually initialized and when do they first come into existence? Is it before the static constructor is called, during, or after?
Many thanks!
The C# Language specification states (in 10.5.5.1 Static field initialization):
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 (§10.12) 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
I believe the guidance in your second line is actually to initialize static fields that are not done inline, using field initializers. In that case, you should use a static constructor to guarantee that they will be initialized prior to usage.
As you can see from the specification, the actual "time" they come into existence is implementation specific, and subject to change. The only guarantee is that they will exist prior to the static constructor being called, which will always occur prior to their usage in code. This specification states (in 10.12):
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 type is created.
· Any of the static members of the class type are referenced.
It's like "normal" fields. So before the static constructor. You can check with a very simple program.
The order is:
static fields
static constructor
"normal" fields
"normal" constructor
A sample program:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start");
int b = A.B;
Console.WriteLine("Read A.B");
new A();
Console.WriteLine("Built A");
}
}
class A
{
public static int B = mystaticfunc();
static int mystaticfunc() {
Console.WriteLine("Static field");
return 1;
}
static A()
{
Console.WriteLine("Static constructor");
}
int C = myfunc();
static int myfunc()
{
Console.WriteLine("Field");
return 1;
}
public A()
{
Console.WriteLine("Constructor");
}
}
Output:
Start
Static field
Static constructor
Read A.B
Field
Constructor
Built A
Static fields are guaranteed to be initialized prior to the first use of the class.
Optionally, you can provide a static constructor to control static initialization at the time it occurs.
The CLR doesn't have separate concepts of static member initialization and static constructor. Instead, there's just a single type initializer.
The C# compiler writes this type initializer for you, first it does initialization of static members, then it includes your code from any static constructor you defined.

Why can I only access static members from a static function?

I have a static function in a class.
whenever I try to use non static data member, I get following compile error.
An object reference is required for the nonstatic field, method, or property member
Why is it behaving like that?
A non-static member belongs to an instance. It's meaningless without somehow resolving which instance of a class you are talking about. In a static context, you don't have an instance, that's why you can't access a non-static member without explicitly mentioning an object reference.
In fact, you can access a non-static member in a static context by specifying the object reference explicitly:
class HelloWorld {
int i;
public HelloWorld(int i) { this.i = i; }
public static void Print(HelloWorld instance) {
Console.WriteLine(instance.i);
}
}
var test = new HelloWorld(1);
var test2 = new HelloWorld(2);
HelloWorld.Print(test);
Without explicitly referring to the instance in the Print method, how would it know it should print 1 and not 2?
Instance methods rely on state of that particular instance in order to run.
Let's say you had this class which has the scenario you describe:
class Person
{
static PrintName()
{
// Not legal, but let's say it is for now.
Console.WriteLine(Name);
}
private Name { get; set; }
}
Hopefully, the problem is apparent now. Because Name is an instance member, you need an actual instance of the class, since Name can be different across different instances.
Because of this, the static method, which is not attached to an instance, doesn't know which instance to use. You have to be explicit in specifying which one.
A static method cannot directly access any non-static member variables of a class.
After all : a static method can be called without an instance of the class even being in existance. How do you want to access a member variable on a non-existing instance??
(of course, as Mehrdad pointed out: you could pass an instance of your class to a static method and access everything on that instance - but that's not what you're talking about, right?)
Static functions can only use static members, and call static functions.
As mentioned, a static function can operate on a class instance, but not from within a class instance (for lack of a more descriptive word). For example:
class MyClass
{
public int x;
public static int y;
public static void TestFunc()
{
x = 5; // Invalid, because there is no 'this' context here
y = 5; // Valid, because y is not associated with an object instance
}
public static void TestFunc2(MyClass instance)
{
instance.x = 5; // Valid
instance.y = 5; // Invalid in C# (valid w/ a warning in VB.NET)
}
}
The definition of a "non static data member" would be an "instance data member". In other words non static members belong to a created instance of your class.
A static method does not run in the context of any specific instance of the class. Hence when you ask such a method to use a non static member it will have no idea which of the 0 or more instances of the class it should try to get the data from.
You can't access non-static data from a static function. This is because the static function can be called irrespective of whether there are any instantiated objects of the class. The non-static data, however, is dependent on a specific object (instantiation) of the class. Since you can't be sure that there are any objects instantiated when calling a static function, it is illogical (and therefore not allowed) to access non-static data from it.
This question has been asked several times on SO in different forms / for different languages:
C#
Java
Python
PHP
Language-independent

Categories

Resources