I am really confused with the real meaning of the static keyword in C#. I have gone through different articles on internet but none of them are really helping me to understand it's meaning and other sources are not trusted. I know Stack Overflow has some brilliant minds who can help me understand the real meaning of static like
When they get initialized.
static methods, properties, classes and constructors
Static vs readonly vs constant
In short, static effectively means "associated with a type instead of any one instance of the type". So there's one set of static variables for a type (within an AppDomain) whether you have 0 instances or a million; you don't need an instance to access a static member, etc.
The exact point of initialization of static variables depends on whether there's also a static constructor or not, but very broadly speaking it's "once, usually before anything significant happens in the class". (See this blog post for a more detailed description.)
While readonly fields can be either static or instance (i.e. related to the type or related to an instance of the type), const values are always implicitly static (they're compile-time constants, so it wouldn't make sense to have one copy per instance).
You may sometimes see static being described as "shared between all instances of a type" - I personally dislike that description, as it suggests that there has to be at least one instance... whereas actually, you don't need any instances in order to use a static member. I prefer to think of them as entirely separate, rather than being "shared" between instances.
I can recommend this article, it seems pretty descriptive:
Static Keyword Demystified
I would also recommend an official c# Programming Guide article which covers the various uses of the static keyword. You can go from there since there are a lot of links to different MSDN articles.: Static Classes and Static Class Members (C# Programming Guide)
A little about constant (const) and readonly:
constant or const is variable which cannot be modified,and which value is known at compile time.
readonly is very similar to constant, this cannot be modified either, the difference is that a readonly field can be modified/initialized once in the constructor. After that readonly is the same as constant.
Using examples:
constant:
const int a=10; // value cannot be modified, value is known at compile time
But what to do when we want constant field whos value is not known at compile time?
e.g const PersonClass a=new PersonClass("name"); // error
The answer is a readonly field:
readonly:
readonly PersonClass a=new PersonClass("name"); // all correct
From documentation:
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
Static members are intializeed on first access to the class and are executed in textual order.
Static methods, properties are parts of the class and not instance.
Static has nothing to do with readonly or constant. Static is a way like a member acessed, readonly and constant is way like a member stored/managed.
Related
As it says. I am about to define a constant, or static, value in a program I am writing and am confused as to why you would use one or the other. As the only related question i get when asking this question deals with someone who wants to mark something as both static and constant at once I suspect I am not the only person a bit lost with these concepts.
So why would I use static and why would I use constant? What's the distinction? Are they synonymous? If so, that's cool, but if not why not? Thanks!
const is dealt with at compile time. Every reference to that constant is replaced by the constant value.
static is very different. It is a variable which exists only once but belongs to all objects of that type. It can be edited unless marked as readonly (or given a getter but no setter). If it is marked as readonly then it is essentially a constant, but it is handled at runtime, not by the compiler.
First off, they are not synonymous.
static marks a member as belonging to the type.
const means the member value cannot be changed. The value is determined at compile time and substituted wherever it appears.
For better understanding of how static is to be used, read Static Classes and Static Members.
And wouldn't you know it five minutes later I find this.
Any other comments?
I have a question concerning type constructors within a Value type. This question was inspired by something that Jeffrey Richter wrote in CLR via C# 3rd ed, he says (on page 195 - chapter 8) that you should never actually define a type constructor within a value type as there are times when the CLR will not call it.
So, for example (well...Jeffrey Richters example actually), I can't work out, even by looking at the IL, why the type constructor is not being called in the following code:
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("This never gets displayed");
}
public Int32 _x;
}
public sealed class Program
{
static void Main(string[] args)
{
SomeValType[] a = new SomeValType[10];
a[0]._x = 123;
Console.WriteLine(a[0]._x); //Displays 123
}
}
So, applying the following rules for type constructors I just can't see why the value type constructor above is not called at all.
I can define a static value type constructor to set the initial state of the type.
A type can have no more than one constructor - there is no default one.
Type constructors are implicitly private
The JIT compiler checks whether the type's type constructor has already been executed in this AppDomain. If not it emits the call into native code, else it doesn't as it knows the type is already 'initialized'.
So...I just can't work out why I can't see this type array being constructed.
My best guess would be that it could be:
The way that the CLR constructs a type array. I would have thought that the static constructor would be called when the first item was created
The code in the constructor is not initializing any static fields so it is ignored. I have experimented with initializing private static fields within the constructor but the field remains the default 0 value - therefore the constructor is not called.
Or...the compiler is somehow optimizing away the constructor call due to the public Int32 being set - but that is a fuzzy guess at best!!
Best practices etc asside, I am just super intrigued by it as I want to be able to see for myself why it doesn't get called.
EDIT: I added an answer to my own question below, just a quote of what Jeffrey Richter says about it.
If anyone has any ideas then that would be brilliant.
Many thanks,
James
The Microsoft C#4 Spec has changed slightly from previous versions and now more accurately reflects the behaviour that we're seeing here:
11.3.10 Static constructors
Static constructors for structs follow
most of the same rules as for classes.
The execution of a static constructor
for a struct type is triggered by the
first of the following events to occur
within an application domain:
A static member of the struct type is referenced.
An explicitly declared constructor of the struct type is called.
The creation of default values
(§11.3.4) of struct types does not
trigger the static constructor. (An
example of this is the initial value
of elements in an array.)
The ECMA Spec and the Microsoft C#3 Spec both have an extra event in that list: "An instance member of the struct type is referenced". So it looks as if C#3 was in contravention of its own spec here. The C#4 Spec has been brought into closer alignment with the actual behaviour of C#3 and 4.
EDIT...
After further investigation, it appears that pretty much all instance member access except direct field access will trigger the static constructor (at least in the current Microsoft implementations of C#3 and 4).
So the current implementations are more closely correlated with the rules given in the ECMA and C#3 specs than those in the C#4 spec: the C#3 rules are implemented correctly when accessing all instance members except fields; the C#4 rules are only implemented correctly for field access.
(The different specs are all in agreement -- and apparently correctly implemented -- when it comes to the rules relating to static member access and explicitly declared constructors.)
From §18.3.10 of the standard (see also The C# programming language book):
The execution of a static constructor for a struct is triggered by the first of the following events to occur within an application domain:
An instance member of the struct is
referenced.
A static member of
the struct is referenced.
An explicitly declared constructor of the
struct is called.
[Note: The creation
of default values (§18.3.4) of struct
types does not trigger the static
constructor. (An example of this is
the initial value of elements in an
array.) end note]
So I would agree with you that the last two lines of your program should each trigger the first rule.
After testing, the consensus seems to be that it consistently triggers for methods, properties, events, and indexers. That means it's correct for all explicit instance members except fields. So if Microsoft's C# 4 rules were chosen for the standard, that would make their implementation go from mostly right to mostly wrong.
Just putting this in as an 'answer' so that I could share what Mr Richter himself wrote about it (does anyone have a link for the latest CLR spec by the way, its easy to get the 2006 edition but finding it a bit harder to get the latest one):
For this kind of stuff, it is usually better to look at the CLR spec than the C# spec. The CLR spec says:
4. 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.
Since none of those conditions are satisfied, the static constructor is not invoked. The only tricky parts to note are that “_x” is an instance field not a static field, and constructing an array of structs does not invoke any instance constructors on the array elements.
Another interesting sample:
struct S
{
public int x;
static S()
{
Console.WriteLine("static S()");
}
public void f() { }
}
static void Main() { new S().f(); }
Update: my observation is that unless static state is used, the static constructor will never be touched - something the runtime seems to decide and doesn't apply to reference types. This begs the question if it's a bug left because it has little impact, it's by design, or it's a pending bug.
Update 2: personally, unless you are doing something funky in the constructor, this behaviour from the runtime should never cause a problem. As soon as you access static state, it behaves correctly.
Update3: further to a comment by LukeH, and referencing Matthew Flaschen's answer, implementing and calling your own constructor in the struct also triggers the static constructor to be called. Meaning that in one out of the three scenarios, the behaviour is not what it says on the tin.
I just added a static property to the type and accessed that static property - it called the static constructor. Without the access of the static property, just creating a new instance of the type, the static constructor wasn't called.
internal struct SomeValType
{
public static int foo = 0;
public int bar;
static SomeValType()
{
Console.WriteLine("This never gets displayed");
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// Doesn't hit static constructor
SomeValType v = new SomeValType();
v.bar = 1;
// Hits static constructor
SomeValType.foo = 3;
}
}
A note in this link specifies that static constructors are not called when simply accessing instances:
http://www.jaggersoft.com/pubs/StructsVsClasses.htm#default
I would guess that you're creating an ARRAY of your value type. So the new keyword would be used to initialize memory for the array.
Its valid to say
SomeValType i;
i._x = 5;
with no new keyword anywhere, which is essentially what you're doing here. Were SomeValType a reference type, you'd have to initialize each element of your array with
array[i] = new SomeRefType();
This is crazy-by-design behavior of "beforefieldinit" attribute in MSIL. It affects C++/CLI too, I filed a bug report where Microsoft very nicely explained why the behavior is the way it is and I pointed out multiple sections in the language standard that didn't agree / need to be updated to describe the actual behavior. But it's not publicly viewable. Anyway, here's the final word on it from Microsoft (discussing a similar situation in C++/CLI):
Since we're invoking the standard
here, the line from Partition I, 8.9.5
says this:
If marked BeforeFieldInit then the
type’s initializer method is executed
at, or sometime before, first access
to any static field defined for that
type.
That section actually goes into detail
about how a language implementation
can choose to prevent the behavior
you're describing. C++/CLI chooses not
to, rather they allow the programmer
to do so if they wish.
Basically, since the code below has
absolutely no static fields, the JIT
is completely correct in simply not
invoking static class constructors.
The same behavior is what you're seeing, although in a different language.
I was plugging away on an open source project this past weekend when I ran into a bit of code that confused me to look up the usage in the C# specification.
The code in questions is as follows:
internal static class SomeStaticClass
{
private const int CommonlyUsedValue = 42;
internal static string UseCommonlyUsedValue(...)
{
// some code
value = CommonlyUsedValue + ...;
return value.ToString();
}
}
I was caught off guard because this appears to be a non static field being used by a static function which some how compiled just fine in a static class!
The specification states (§10.4):
A constant-declaration may include a
set of attributes (§17), a new
modifier (§10.3.4), and a valid
combination of the four access
modifiers (§10.3.5). The attributes
and modifiers apply to all of the
members declared by the
constant-declaration. Even though
constants are considered static
members, a constant-declaration
neither requires nor allows a static
modifier. It is an error for the same
modifier to appear multiple times in a
constant declaration.
So now it makes a little more sense because constants are considered static members, but the rest of the sentence is a bit surprising to me. Why is it that a constant-declaration neither requires nor allows a static modifier? Admittedly I did not know the spec well enough for this to immediately make sense in the first place, but why was the decision made to not force constants to use the static modifier if they are considered static?
Looking at the last sentence in that paragraph, I cannot figure out if it is regarding the previous statement directly and there is some implicit static modifier on constants to begin with, or if it stands on its own as another rule for constants. Can anyone help me clear this up?
UPDATE: This question was the subject of my blog on June 10th, 2010. Thanks for the great question!
why was the decision made to not force constants to use the static modifier if they are considered static?
Suppose constants are considered to be static. There are three possible choices:
Make static optional: "const int x..." or "static const int x..." are both legal.
Make static required: "const int x..." is illegal, "static const int x..." is legal
Make static illegal: "const int x..." is legal, "static const int x..." is illegal.
Your question is why did we choose (3)?
The design notes from 1999 do not say; I just checked. But we can deduce what was probably going through the language designer's heads.
The problem with (1) is that you could read code that uses both "const int x..." and "static const int y..." and then you would naturally ask yourself "what's the difference?" Since the default for non-constant fields and methods is "instance" unless "static", the natural conclusion would be that some constants are per-instance and some are per-type, and that conclusion would be wrong. This is bad because it is misleading.
The problem with (2) is that first off, it is redundant. It's just more typing without adding clarity or expressiveness to the language. And second, I don't know about you, but I personally hate it when the compiler gives me the error "You forgot to say the magic word right here. I know you forgot to say the magic word, I am one hundred percent capable of figuring out that the magic word needs to go there, but I'm not going to let you get any work done until you say the magic word".
The problem with (3) is that the developer is required to know that const logically implies static. However, once the developer learns this fact, they've learned it. It's not like this is a complex idea that is hard to figure out.
The solution which presents the fewest problems and costs to the end user is (3).
It is interesting to compare and contrast this with other places in the language where different decisions were made.
For example, overloaded operators are required to be both public and static. In this case, again we are faced with three options:
make public static optional,
make it required, or
make it illegal.
For overloaded operators we chose (2). Since the natural state of a method is private/instance it seems bizarre and misleading to make something that looks like a method public/static invisibly, as (1) and (3) both require.
For another example, a virtual method with the same signature as a virtual method in a base class is supposed to have either "new" or "override" on it. Again, three choices.
make it optional: you can say new, or override, or nothing at all, in which case we default to new.
make it required: you have to say new or override, or
make it illegal: you cannot say new at all, so if you don't say override then it is automatically new.
In this case we chose (1) because that works best for the brittle base class situation of someone adds a virtual method to a base class that you don't realize you are now overriding. This produces a warning, but not an error.
My point is that each of these situations has to be considered on a case-by-case basis. There's not much general guidance here.
Basically, const implies static already, since the value cannot be changed at runtime. There's no reason for you to ever declare static const, since it's already implied, and the language designers decided to make the language syntax reflect that.
The specification language is basically saying "Const is always static, so you can't explicitly say static and const since it's redundant."
It isn't required or allowed because it's redundant. If all const members are static, then only confusion can arise from allowing some of them to be specified as static and some of them not to be.
Another reason to disallow declare constants as static is that from CLR point of view the constants are not not stored in memory along with other static fields of the type.
The constants don't have memory address and you cannot get reference to the constant value (the only exception is string constants). At runtime the type holding constant definition won't be loaded if other static/nonstatic members are not referenced. If it is the only type in the assembly, you can even safely delete it's DLL from the disk after compilation.
So, the constants are 'static' only in terms of 'may be referenced from static methods'. Constants do not have any other 'static' properties as other static type members do.
What is the equivalent of Java's final in C#?
The final keyword has several usages in Java. It corresponds to both the sealed and readonly keywords in C#, depending on the context in which it is used.
Classes
To prevent subclassing (inheritance from the defined class):
Java
public final class MyFinalClass {...}
C#
public sealed class MyFinalClass {...}
Methods
Prevent overriding of a virtual method.
Java
public class MyClass
{
public final void myFinalMethod() {...}
}
C#
public class MyClass : MyBaseClass
{
public sealed override void MyFinalMethod() {...}
}
As Joachim Sauer points out, a notable difference between the two languages here is that Java by default marks all non-static methods as virtual, whereas C# marks them as sealed. Hence, you only need to use the sealed keyword in C# if you want to stop further overriding of a method that has been explicitly marked virtual in the base class.
Variables
To only allow a variable to be assigned once:
Java
public final double pi = 3.14; // essentially a constant
C#
public readonly double pi = 3.14; // essentially a constant
As a side note, the effect of the readonly keyword differs from that of the const keyword in that the readonly expression is evaluated at runtime rather than compile-time, hence allowing arbitrary expressions.
It depends on the context.
For a final class or method, the C# equivalent is sealed.
For a final field, the C# equivalent is readonly.
For a final local variable or method parameter, there's no direct C# equivalent.
What everyone here is missing is Java's guarantee of definite assignment for final member variables.
For a class C with final member variable V, every possible execution path through every constructor of C must assign V exactly once - failing to assign V or assigning V two or more times will result in an error.
C#'s readonly keyword has no such guarantee - the compiler is more than happy to leave readonly members unassigned or allow you to assign them multiple times within a constructor.
So, final and readonly (at least with respect to member variables) are definitely not equivalent - final is much more strict.
As mentioned, sealed is an equivalent of final for methods and classes.
As for the rest, it is complicated.
For static final fields, static readonly is the closest thing possible. It allows you to initialize the static field in a static constructor, which is fairly similar to static initializer in Java. This applies both to constants (primitives and immutable objects) and constant references to mutable objects.
The const modifier is fairly similar for constants, but you can't set them in a static constructor.
On a field that shouldn't be reassigned once it leaves the constructor, readonly can be used. It is not equal though - final requires exactly one assignment even in constructor or initializer.
There is no C# equivalent for a final local variable that I know of. If you are wondering why would anyone need it: You can declare a variable prior to an if-else, switch-case or so. By declaring it final, you enforce that it is assigned at most once.
Java local variables in general are required to be assigned at least once before they are read. Unless the branch jumps out before value read, a final variable is assigned exactly once. All of this is checked compile-time. This requires well behaved code with less margin for an error.
Summed up, C# has no direct equivalent of final. While Java lacks some nice features of C#, it is refreshing for me as mostly a Java programmer to see where C# fails to deliver an equivalent.
Java class final and method final -> sealed.
Java member variable final -> readonly for runtime constant, const for compile time constant.
No equivalent for Local Variable final and method argument final
http://en.csharp-online.net/CSharp_FAQ:_What_are_the_differences_between_CSharp_and_Java_constant_declarations
C# constants are declared using the const keyword for compile time constants or the readonly keyword for runtime constants. The semantics of constants is the same in both the C# and Java languages.
sealed
Why does C# not allow const and static on the same line? In Java, you must declare a field as 'static' and 'final' to act as a constant. Why does C# not let you declare const's as final?
I make the further distinction that in Java, every interface is public and abstract, whether this is explicitly declared or not. Aren't const's effectively static in nature? WHy does C# balk at this?
const and static really do mean different things, different storage mechanism, different initialisation. static is read/write, therefore must have memory allocated for storage and must be initialised at runtime. A static can be initialised with a literal value or an expression. In contrast, a const is immutable and must be initialised with a compile time constant (typically a literal value, or an expression that can be fully evaluated at compile time). The value is known at compile time so it can be embedded directly in the generated code, therefore requires no storage to be allocated at runtime.
Constants by their nature are static, so that would be redundant.
As said before, static final in Java is the same as static readonly in C#. In fact, you are saying that this member is static and its content can't be changed. Also you can specify in both cases the value from static constructor.
But const in C# is completely different thing. It's more along the lines of constants in C (DEFINE directives) but with OOP in mind. It's static because it's constant - every instance would have this constant with the same value, no constructor can set it. Also it's possible that someone would like to access the constant without having to create an instance. When you think about it non-static constant just doesn't make sense. You can almost say that constants are not part of an object - they just use it to provide context, a strong name.
Java doesn't have an equivalent to const. You can read somewhere that static final is equivalent to DEFINE but that's just so vague. Completely different mechanism, nothing in common but in the end result in the code is the same - better maintainability and readability of the code.
You just have to stop thinking about constants in C# as static members because they are not. Think of them as OOP version of DEFINE. When you consider encapsulation only reason for final and readonly fields is to prevent your own code from accidently changing its value. And that doesn't sound like constant to me.
Sumary:
final = readonly
static final = static readonly
N/A = const
It is true that a C# const implies static BUT, C# has an equivalent to Java's final keyword in the keyword readonly.
So, in fact, C# allows a const final, it is static readonly in C#.
Because allowing and not requiring modifiers that are inherent can cause confusion. If you see
static const int A = 3
const int B = 5
you may believe that they are 2 different kinds of constants.
Even VB 2008 (which can be very verbose if you wish) doesn't allow that.