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.
Related
I am trying to declare a PI constant like this:
public static const double PI = Math.PI;
but why am I getting this error?
The constant 'Calendar.NewCalendar.PI' cannot be marked static
const implies static (you don't need an instance to reference the const value).
I want to also add this important point: When you link against (reference) an assembly with a public const, that value is copied into your assembly. So if the const value in the referenced assembly changes, your assembly will still have the originally compiled-in value.
If this behavior is not acceptable, then you should consider making the field a public static readonly field.
Lib.dll, provided as binary:
public class Foo {
public const int HATS = 42;
public static readonly int GLOVES = 33;
}
App.exe, references Lib.dll:
Foo.HATS // This will always be 42 even if the value in Lib.dll changes,
// unless App.exe is recompiled.
Foo.GLOVES // This will always be the same as Foo.GLOVES in Lib.dll
From MSDN:
Don’t create a constant to represent information that you expect to change at any time. For example, don’t use a constant field to store the price of a service, a product version number, or the brand name of a company. These values can change over time, and because compilers propagate constants, other code compiled with your libraries will have to be recompiled to see the changes.
From DotNetPerls:
DLLs. When you use a const field or declaration, the C# compiler actually embeds the const variable's value directly in the IL code. Therefore, it essentially erases the const as a separate entity.
Caution:
If programs that depend on a const are not recompiled after the const value changes, they may break [because they'll continue to use the previous value].
A constant is static by definition.
You can't have static const. Try readonly instead of const or simply drop the "static" since "const" is implied static anyway.
Constants cannot be replaced in the code during compilation, not runtime, so there's no requirement for static vs instance definitions.
All constants declarations are implicitly static, and the C# specification states that the (redundant) inclusion of the static modifier is prohibited. I believe this is to avoid the confusion which could occur if a reader were to see two constants, one declared static and one not – they could easily assume that the difference in specification implied a difference in semantics. Having said that, there is no prohibition on redundantly specifying an access modifier which is also the default one, where there is a choice. For instance, a (concrete) method can be explicitly marked as private despite that being the default. The rule appears to be that where there is no choice (e.g. a method declaration in an interface) the redundant modifier is prohibited. Where there is a choice, it’s allowed.
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 got a bit of a surprise today when I changed the value of a publicly-visible constant in a static class and then replaced an old copy of the assembly with the newly-compiled version. The surprise was that the existing program that referenced the assembly didn't pick up the new value of the constant. That is, I didn't re-compile the executable but rather just replaced that one assembly.
A full description of my experiment is at How constant is a constant?
I'll admit to being very surprised by this behavior. I understand what's going on, but I don't understand why. Is there a particular technical reason why constants couldn't be picked up at JIT time rather than compile time? Are there cases where doing that would break things?
Constants are supposed to be constant. For all time. Constants are things like the value of pi, or the number of protons in a lead atom.
If your constant changes, it wasn't really a constant; use a readonly field instead.
Also see the Framework Design Guidelines, which state:
Use constant fields for constants that will never change. The compiler burns the values of const fields directly into calling code. Therefore const values can never be changed without the risk of breaking compatibility.
Essentially, changing a constant without recompiling everything that depends on it is every bit as broken as changing the signature of a method without recompiling everything that depends on it. The compiler "bakes in" all kinds of assumptions about information about metadata from referenced assemblies when it compiles a dependent assembly. If you make any change, you cannot expect things to simply keep on working.
There is also a third way to declare "constants": a public static property.
public static string ConstString {get{return "First test";}}
This has the versioning semantics of a readonly field, but if the jitter inlines the getter it becomes a jit-time constant. And unlike const it can be used on user defined types.
I think it's a good idea to use static properties for value-types and string, but not for user defined classes, since you don't want to allocate a new instance on each property access.
I used this in my FixedPoint type like this:
public struct FixedPoint
{
private int raw;
private const fracDigits=16;
private FixedPoint(int raw)
{
this.raw=raw;
}
public static FixedPoint Zero{get{return new FixedPoint();}}
public static FixedPoint One{get{return new FixedPoint(1<<fracDigits);}}
public static FixedPoint MaxValue{get{return new FixedPoint(int.MaxValue);}}
}
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