C# - Static Member only operate on static data? - c#

From MSDN document i understand ( I am not sure,i understand perfectly ) :
Static members can operate only on static data and call static methods of the
defining class.
I worked out the following code :
class Test
{
static int i;
public static void StaticDemo()
{
int v;
i=10;
v=10*i;
Console.WriteLine("The value of i={0}",v);
}
}
In the above example the declaration int v inside the method StaticDemo( ) is not static field. Then how did the operation v = 10 * i work ?

The MSDN documentation refers to the fact that you cannot access instance members within a static method if you don't pass in an instance. Of course, every method can declare local variables and use them.

The int v is local to the function, and therefore not a class member as such. (I.e. it doesn't need an instance of the class)

Functions can always operate on local variables irrespective of whether they are static. Since v is declared within your StaticDemo function it is a local variable (i.e. only accessible within the function).
What the documentation is referring to is that you cannot access instance variables within a static method. So if instead of declaring i as 'static int i;' you had declared it as 'int i;' the StaticDemo method would not have been able to access it, since it would be an instance variable (i.e. not static).

Because v does not belong to the defining class but to the method and thus can be operated on by the method.

It works because v is local to the static function itself. If v was defined in the body of the Test class, it would not.

Because variables defined inside a method are not either static or instance... They are locally scoped to the method itself.
They are stored in the method's stack frame, and have nothing to do either with the instance, or with the class.

Because it doesn't have any scope beyond the static method. In other words, there is no state being kept on the method

Related

in C# why static fields are not initialized after creating first instance of that type (in case of having no static constructor) [duplicate]

DependencyProperty.AddOwner MSDN page offers an example with two classes with static members, and the member of one class depends on the member of the other class for initialization. I think MSDN is wrong - the initialization order of static variables is unreliable in C# just like it is in C++ or anywhere else. I'm probably wrong because the WPF library itself is written that way and it works just fine. What am I missing? How can C# compiler possibly know the safe initialization order?
It's fine for one type to depend on another type being initialized, so long as you don't end up in a cycle.
Basically this is fine:
public class Child
{
static Child() {} // Added static constructor for extra predictability
public static readonly int X = 10;
}
public class Parent
{
static Parent() {} // Added static constructor for extra predictability
public static readonly int Y = Child.X;
}
The result is well-defined. Child's static variable initializers are executed prior to the first access to any static field in the class, as per section 10.5.5.1 of the spec.
This isn't though:
public class Child
{
public static readonly int Nasty = Parent.Y;
public static readonly int X = 10;
}
public class Parent
{
public static readonly int Y = Child.X;
}
In this latter case, you either end up with Child.Nasty=0, Parent.Y=10, Child.X=10 or Child.Nasty=0, Parent.Y=0, Child.X=10 depending on which class is accessed first.
Accessing Parent.Y first will start initializing Parent first, which triggers the initialization of Child. The initialization of Child will realise that Parent needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the first set of numbers - because Child.X ends up being initialized before its value is used for Parent.Y.
Accessing Child.Nasty will start initializing Child first, which will then start to initialize Parent. The initialization of Parent will realise that Child needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the second set of numbers.
Don't do this.
EDIT: Okay, more detailed explanation, as promised.
When is a type initialized?
If a type has a static constructor, it will only be initialized
when it's first used (either when a static member is referenced, or
when an instance is created). If it doesn't have a static
constructor, it can be initialized earlier. In theory, it could also
be initialized later; you could theoretically call a constructor or
a static method without the static variables being initialized - but
it must be initialized before static variables are referenced.
What happens during initialization?
First, all static variables receive their default values (0, null
etc).
Then the static variables of the type are initialized in textual
order. If the initializer expression for a static variable requires
another type to be initialized, then that other type will be
completely initialized before the variable's value is assigned -
unless that second type is already being initialized (due to a
cyclic dependency). Essentially, a type is either:
Already initialized
Being initialized at the moment
Not initialized
Initialization is only triggered if the type is not initialized.
This means that when there are cyclic dependencies, it is possible
to observe a static variable's value before its initial value has
been assigned. That's what my Child/Parent example shows.
After all the static variable initializers have executed, the static
constructor executes.
See section 10.12 of the C# spec for more details on all of this.
By popular demand, here was my original answer when I thought the question was about the initialization order of static variables within a class:
Static variables are initialized in textual order, as per section 10.5.5.1 of the C# spec:
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.
Note that partial types make this trickier as there's no one canonical "textual order" of the class.
If you are concerned about the order you could always place your code in the static constructor. This is where I register my dependency properties.
No I think unreliable is not the correct word here.
In true single thread scenario, static members of class are initialized when any of static members of the type is first accessed in your code.
I am not aware of c++, but yes only in certain cases like in Multi threaded environment if two types trying to access shared resource and if that is static then its impossible to tell who will win and which one will work correct.
The MSDN Example is correct and that will work correctly.

C# unassigned static int results to zero

while experimenting static variables I was amazed to know why the static "int" result to 0 (zero) and non-static result to compile time error.
Consider Case 1
static int i;
static void Main()
{
Console.Write("Value of i = " + i);
Console.ReadKey();
}
the output is
Value of i = 0
Case 2 with removing static
static void Main()
{
int i;
Console.Write("Value of i = " + i);
Console.ReadKey();
}
And the output for this will result to compile time error
Error 1 Use of unassigned local variable 'i'
question here is how do both cases differ i.e first one result to 0 and another get compiler error.
The existing answers all miss something important here, which is where the variable is declared. Is it a class variable or a local variable
In the first scenario
class Program
{
static int i;
static void Main()
{
Console.Write("Value of i = " + i);
Console.ReadKey();
}
}
The variable i is declared as a class variable. Class variables always get initialized, it doesn't matter if it's static or not. If you don't provide a default value, the variable is assigned default, which in the case of int is 0.
On the other hand, in the second example
class Program
{
static void Main()
{
int i;
Console.Write("Value of i = " + i);
Console.ReadKey();
}
}
Variable i is local variable. Unlike class variables, local variables are never initialized with a default value implicitly, but only when you explicitly initialize them. So the compiler error comes not from the variable being static or not, but from the difference in initialization between local and class variables.
The specification shares some more details on that: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables, especially sections 9.2 Variable Types and 9.3 Default Values.
The interesting parts are
9.2.2 The initial value of a static variable is the default value (§9.3) of the variable’s type.
9.3.2.2 The initial value of an instance variable of a class is the default value (§9.3) of the variable’s type.
9.2.8 A local variable introduced by a local_variable_declaration is not automatically initialized and thus has no default value. Such a local variable is considered initially unassigned.
9.3: The following categories of variables are automatically initialized to their default values:
Static variables.
Instance variables of class instances.
Array elements.
The underlying reason for this has to do with memory management. When you initialize a class with new() the garbage collector zeros out all bytes on the heap, thus basically defaulting the value of the variable. In case of integers this is 0, for an object reference it would be a null.
Since local variables live on the stack, and the garbage collector doesn't live work on the stack, this guarantee does not exist, so we have explicitly initialize a variable before using it.
by definition of the C# language, types have "default values", which are assigned to them if you don't assign something else. numbers have a default value of 0, boolean - false, reference types - null, and structs - each member by it's type.
Based on my limited understanding, by declaring a variable as static, it becomes existing in memory and is assigned a default value of 0, and does not depend on an instance of the class it is in to exist.
If it is not defined as static, it needs to be initialized within the class(as in, given a value) before it can be used in any logic/math.
Now my confusion comes from being very new, and trying to understand exactly WHY you would choose to do something like this one way, instead of another. Perhaps this is a way to have some values that persist that may be necessary even when the class it is in is not existing, and making everything static would result in ineficient use of memory.
The fundamental reason why you do not get a compilation error for the static scenario is because the compiler has no way to be sure that it is not initialized before being read.
Indeed, a static class member without visibility modifier is internal by default. This means that another class of the same assembly could define it before the Main method is called.
And even if it were private, an external code could still define its value using classes in the System.Reflection namespace.
Whereas, for the local variable case, the compiler is sure that no other code could define the variable between its declaration and its first reading.
Indeed, local variables are not accessible outside their declaration scope to non debugging code.

Singleton in DLL being destroyed

I have C++ wrapped in C dll. The dll is called in my C# project.
In my wrapper functions I call a lot of Singletons, they are setup as follows:
ComponentManager &ComponentManager::_cmpManager()
{
static ComponentManager ONLY_ONE;
return ONLY_ONE;
}
The above function is a static function inside my ComponentManager class.
Here is the specific problem:
bool createNewEntity(char *c)
{
if (ComponentManager::_cmpManager().nameAvailable(c))
{
Entity e(c);
Transform t;
ComponentManager::_cmpManager().addComponent(c, t);
SceneNode sc(CMP_MANAGER2.getComponent<Transform>(c));
SCENE_MANAGER.addSceneNode(sc, e.entityName);
return true;
}
return false;
}
Essentially what this does is the singleton has a Hash Map with a key type string, this function checks to see if this key already exists. The behaviour is always returning true. When I use a global object of type componentManager instead of the singleton it behaves correctly, so something is telling me the singleton keeps leaving scope and deleting itself. Also if I use the singleton in an application exe rather than a dll it behaves correctly. So I have 2 questions,
Is there a way to keep my singleton from traveling out of scope? If
not.
Is there another way of setting up singletons to not be deleted
after leaving scope?
C++ static keyword is a bit different from C# static.
See https://msdn.microsoft.com/en-us/library/y5f6w579.aspx for description.
In item 2 there it says: 2. When you declare a variable in a function, the static keyword specifies that the variable retains its state between calls to that function.
Try to declare your static not inside the method but in class scope (as per item 3 in above reference).
3. When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. A static data member must be defined at file scope. An integral data member that you declare as const static can have an initializer.
You will also need to declare that static member at file scope.
Why it works when it is not in a dll -- it is not exactly clear. Probably a peculiar behaviour of linker. If class is declared in a dll it probably tries to instantiate class every time and your static inside the function is a new one every time. But if class is inside the exe file it is somehow the same class every time and when you call your method _cmpManager() it always accesses the same instance of the class.
Just my two cents :-).

Ambiguity in initialization order of static variables

During my research into the best way to build a Singleton in C# I stumbled across the following article where there is a brief mention that in C++
"The C++ specification left some ambiguity around the initialization
order of static variables."
I ended up looking into the question and found this and this. Where basically the point (as far as I understand) is that the initialization order of static variables in C++ is undefined. Ok I guess so far so good, but then I wanted to understand the following statement that the article later makes
"Fortunately, the .NET Framework resolves this ambiguity through its
handling of variable initialization."
So I found this page where they say
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.
and give the example of
using System;
class Test
{
static void Main() {
Console.WriteLine("{0} {1}", B.Y, A.X);
}
public static int F(string s) {
Console.WriteLine(s);
return 1;
}
}
class A
{
static A() {}
public static int X = Test.F("Init A");
}
class B
{
static B() {}
public static int Y = Test.F("Init B");
}
the output must be:
Init B
Init A
1 1
"Because the rules for when static constructors execute (as defined in
Section 10.11) provide that B's static constructor (and hence B's
static field initializers) must run before A's static constructor and
field initializers."
But where I am confused is that my understanding was that the initialization order of static variables in these examples would be based on when a method or field within the class was first invoked, which is in turn based on the execution order of the block of code (this case left to right). IE: Completely independent of where - or the order - of the class declaration. Yet by my interpretation of that article it says its as a result of the order of declaration of those classes, which my testing doesn't back up?
Could someone please clarify this (and the point the article is trying to make) for me and perhaps provide a better example that illiterates the behaviour described?
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.
This means that within the same class, static fields are initialized in order of appearance in the source code. For example:
class A
{
public static int X = Test.F("Init A.X");
public static int Y = Test.F("Init A.Y");
}
When it's time for the static fields to be initialized, X is guaranteed to be initialized before Y.
"Because the rules for when static constructors execute (as defined in
Section 10.11) provide that B's static constructor (and hence B's
static field initializers) must run before A's static constructor and
field initializers."
This means that the static constructor and member initialization for each class will run in evaluation order when expressions that access these classes appear¹. The relative order of appearance of the class definitions in source code does not play any role, even if they appear in the same source file (which they most certainly are not obliged to do). For example:
static void Main() {
Console.WriteLine("{0} {1}", B.Y, A.X);
}
Assuming that neither A nor B has already been statically initialized, order of evaluation guarantees that all the fields of B will be initialized before any field of A. The fields of each class will be initialized in the order specified by the first rule.
¹ for the purposes of this discussion I am ignoring the existence of beforefieldinit.
In C++ the order of initialization of variables with static storage duration in a single translation unit is the order in which the definitions of such variables occur. It is unspecified what the order of initialization of variables with static storage duration is across different translation units.
That is, the C++ standard does offer a similar guarantee to what you quoted, substituting the order of declaration in the class for the order of definition in the single translation unit that defines such variables. But that is not the important difference.
While in C++ that is the only guarantee, in C# there is the added guarantee that all static members will be initialized before the first use of the class. This means that, if your program depends on A (consider each type in a different assembly which is the worst case), it will start the initialization of all static fields in A, if A in turn depends on B for any of those static initializations, then the initialization of B static members will be triggered there.
Contrast that with C++, where during static initialization[*], all other variables with static duration are assumed to be initialized. This is the main difference: C++ assumes that they are initialized, C# ensures that they are before that use.
[*] Technically the case where this is problematic could be dynamic initialization in the standard. Initialization of variables with static storage duration inside a each translation unit is a two step process, where during the first pass static initialization sets the variables to a fixed constant expression, and later in a second pass called dynamic initialization all variables with static storage whose initializer is not a constant expression are initialized.

C# question for VBer. Do private fields have to be declared Static?

I am a vb.net programmer switching to C#.
I have the following code for a console application (targeting NET20)
using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace eScoreSwapper
{
class Program
{
private string _dbName = ConfigurationManager.AppSettings["dbName"];
static void Main(string[] args) {}
static void InitVars()
{
if (string.IsNullOrEmpty(_dbName)) _dbName = "";
}
}
}
This is giving a compile error in the if clause of InitVars for the _dbName variable:
Error 1 An object reference is required for the non-static field, method, or property 'eScoreSwapper.Program._dbName' C:\Users\SethS\Documents\eScore\Versions\Trunk\dotNet\eScoreSwapper\eScoreSwapper\Program.cs 26 38 eScoreSwapper
Is it because it is true. C# does not allow you to reference private class fields unless they are declared static? I am sure I am doing something wrong.
While I am at it can I ask another C# question. Why is the if statement valid? Why are braces not required? Is it valid syntax as long as if condition is followed by a single expression (as in t-sql IF ).
Thanks for your help.
Seth
No, but private fields used by static method do. What I think you really want to do is remove the static from the declaration of InitVars().
I'm gonna assume that you previously tried:
static void Main(string[] args)
{
InitVars();
}
and that failed, so you added the static to InitVars(). Wrong answer. Basically, you should pretend Main() is not part of the class.
static void Main(string[] args)
{
Program prog = new Program();
prog.InitVars();
}
As far the If() statement
if (string.IsNullOrEmpty(_dbName)) _dbName = "";
is just a short version of:
if (string.IsNullOrEmpty(_dbName))
_dbName = "";
Now, in C-ish language, officially, an if() that is true, will execute the (one) next statement. But, you can make several statement into one statement, by wrapping them in curly-braces. But, if you really only have one statement, they aren't needed.
You can't use an instance member variable in a static method. Either make your variable static or put the method and variable in an instance class and new it up in main on program.
The reason you can't access an instance variable from a static method becomes obvious when you think about the fact that the method exists "on the class" while the variable exists "on the instance". Hope that helps.
As a final comment, I'd just add that the fact that the compiler is giving you the error has nothing to do with the fact that your field is private; if your field was public, internal, etc. the compiler would still give you the same error: ie. static methods can't access instance variables.
You can't access a non-static member in a static method.
Braces are not required unless you want it to apply to more than one statement. But you should put them anyways.
You can't access a non-static class member from within a static method without using a method parameter to bring a reference of the class member in.
The if syntax is normal c# (c++, c). Braces are only required for complex, multi-line blocks. The following else can have a singular line as well.
To answer the question about braces, they are only truly mandatory in C# if there is more than one statement in the if block. Otherwise, you can put your one-liner on the same line as the if, or on the next line. I believe that it is generally advised in coding standards that you always use the brackets. It is always often advised not to put the entire series of code on all one line, but that kind of went out the window when we got tertiary and null coalescing operators.
You're trying to access an instance field from a static context. Since _dbName isn't marked static, it could possibly be different for each instance of the Program class, so the static method InitVars() has no way of knowing what the right value is.
If every single instance of Program will have the same value for _dbName, then _dbName should be marked static. If different instances may have different values, then InitVars() should be an instance method (remove the static keyword and only invoke it on actual Program objects rather than from the static Main).
"static" in VB parlance would be "shared".

Categories