How are C# const members allocated in memory? [duplicate] - c#

This question already has an answer here:
Memory allocation for const in C#
(1 answer)
Closed 8 years ago.
The title of the question is self explanatory. I wonder if a member that is declared const is singleton for all instances of the class or each instance has it's own copy.
I've read some questions about const but most of them refer to const variables inside a method.

C# constants are implemented as fields with the literal constraint in the Common Language Instructructure. Looking up ECMA-335 §I.8.6.1.2 provides the definitive answer (emphasis mine):
The literal constraint promises that the value of the location is
actually a fixed value of a built-in type. The value is specified as
part of the constraint. Compilers are required to replace all
references to the location with its value, and the [Virtual Execution System] therefore need
not allocate space for the location. This constraint, while logically
applicable to any location, shall only be placed on static fields of
compound types. Fields that are so marked are not permitted to be
referenced from CIL (they shall be in-lined to their constant value at
compile time), but are available using reflection and tools that
directly deal with the metadata.
So there you go, the values of const fields must be copied by compilers directly into the instruction stream (typically using ldc.* instructions). They do not exist in a referencable location, but need to be available in the metadata and via reflection. They could be implemented like static fields, but do not have to.

Constants are usually something that can be evaluated compile time and compiler is likely to replace it with the evaluated value.
Also Const means static (see link below)
A constant expression is an expression that can be fully evaluated at
compile time. Therefore, the only possible values for constants of
reference types are string and null.
Source:
C# static and const variables memory
Memory allocation for const in C#
C# do const fields use less memory?

const implies static so there is only one instance per class.
Edit: Add Reference

Constants are resolved at compile time, and the actual value of the constant is stored in the compiled DLL in place of references to the constant.
In addition, the constant is saved as a member of the class in the DLL. This allows public constants to be referenced by external DLLs. However, the external references are also converted into the constant value when they are compiled.
A ramification of the compile properties of constants means that if DLL1 refers to a constant in an external DLL2, and the constant definition in DLL2 changes, then DLL1 will not have the updated value unless it is recompiled, too.
If you want to work around this problem, you're better off with public properties returning the constant. See the answer to this question for more information.
I confirmed the above behavior with .NET Reflector.

I believe that value itself is in-lined anywhere it's referenced at compile time. Meaning, if I have const int x = 10; and then I use x 100 times throughout my source, each of those 100 references to x will actually just be replaced by 10 prior to the actual compilation.

Const is meta-data...
It is not in memory, but using the const - telling the compiler "you see the literal under the name of that const... put it here" (literal is a number, or string, or null, in the middle of the code, like in for (int i = 0... that 0 is literal).
Now, in most cases - these (literals.. from now on - we're talking about literals) are value types... what singleton has to do with value types?! Nothing... The data of a value type is copied from one location to another. so it cannot be a singleton.
What about nulls? null is a possible value of a reference, which signals "I'm referencing nothing" - So again.. Singleton is irrelevant here (For nullable value types - null is just like the default constructor... And they're value types... So this is like case 1).
And what about string literals?! (eg: "hello world" in the middle of the code)
This is a special case.
Every string literal is cached inside an intern table... So - every time you use the same string-literal - you're actually referencing the same object in memory.
But is doesn't mean that every string with the same value is the same object:
string ab = "ab";
string anotherAB = "ab";
string another = 'a'.ToString() + 'b'.ToString();
Console.WriteLine(object.ReferenceEquals(ab, anotherAB)); // true
Console.WriteLine(object.ReferenceEquals(ab, "ab")); // true
Console.WriteLine(object.ReferenceEquals(ab, another)); // false
Console.WriteLine(object.ReferenceEquals("ab", another)); // false

Related

Why use constants instead of static properties? [duplicate]

I am eager to know the difference between a const variable and a static variable.
Is a const variable also always static? What is the difference between them?
const fields can only hold value types or System.String. They must be immutable and resolvable at compile-time.
static readonly fields can and generally do hold reference types, which (other than strings) can only be created at runtime. These can (but shouldn't) be mutable types; the only thing that cannot change is the reference itself.
If you need to maintain a "constant" set of instances that are reference types, you generally do it with a set of public static readonly fields, such as the members of System.Drawing.SystemColors.
Last but not least, initialization of a readonly field can be deferred until the execution of a constructor, which means that it even though it can only be written to once, it does not always have to be initialized with the exact same value. True constants declared with const can only ever have a single value (specified at compile time).
One subtle but crucial difference is that consts are evaluated at compile time, whereas statics are evaluated at run time. This has an important impact on versioning. For example, suppose you write:
public const int MaxValue = 100;
You compile and ship your assembly (Assembly A). Then someone else writes an assembly (Assembly B) which references MaxValue. In this case, the value 100 is compiled into their assembly as well as yours.
If you had written this:
public static readonly int MaxValue = 100;
then the reference in their assembly would remain just that, a reference. When someone ran Assembly B, the value 100 would be loaded from your assembly, Assembly A.
This can, for example, affect simple patching scenarios. If you issue an updated Assembly A where MaxValues is declared as 200, and the user copies that version over the previous version (but does not recompile Assembly B), then in the first scenario Assembly B will continue to operate as if MaxValues were 100, because that's the const value that was compiled into Assembly B. In the second scenario, Assembly B will pick up the new value because it loads the non-const static variable at runtime.
As you say, both static and const are attached to a type rather than an instance of a type. However, you can still change static items. You cannot change const items.
Be careful with this, though. If your const item is a reference type, the assigned expression has to be evaluated at compile time, and that means that the only possible value you can give the reference is null (with the notable and useful exception of strings).
A (non-readonly) static can be changed after it has been declared whereas a constant cannot. In addition, a constant cannot be set using a function whereas a static variable can.
A constant is a variable that cannot be changed in value.
A static is a variable that cannot be used outside the scope of it's declaration. That is, if it is a global variable then it can only by used in the file that declares it. If it is a variable inside a function, then it can be use only inside that function.

Does C# provide "correct" const for reference type objects? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
New to C#. After reading MS programming guide and several online tutorials, I found out that member of readonly reference type object (class) can be changed (and const can be applied to build-in types):
public readonly Point Origin = new Point { X = 0, Y = 0 };
Origin.X = 7; // compiles and works !!
Compared to C++ const correctness, C# implementation of const seems like a huge flaw in the language design. I am missing something ? Is there any other way to guarantee constant correctness of reference type objects ?
Compared to C++ const correctness, C# implementation of const seems like a huge flaw in the language design.
It is not. Actually, the opposite is true.
Is there any other way to guarantee constant correctness of reference type objects ?
So-called "const correctness" in C/C++ is a misnomer.
Suppose I have a program with zero undefined behaviour in it. And suppose I have a reference to foo with field bar, and I pass it via const reference to method blah. Do I have any guarantee that in this fully-defined program when blah returns, foo.bar is unchanged, regardless of what blah does? Absolutely not! Suppose I am implementing method blah and I have a const reference to the foo. Do I have any guarantee that throughout the operation of blah, bar will not be observed to change? Absolutely not!
The invariant that I want is "this thing will not be observed to change"; what I get in C++ is "you're not allowed to change this thing via this reference". The useful invariant implied by so-called "const correctness" that I would like to have is not actually guaranteed.
By contrast in C# a constant field is something you can rely on; that thing is going to stay the same no matter how many times you look at it.
Well, it may seem wrong or not, depending on your criteria/requirements.
This:
public readonly SomeClass Name = new SomeClass();
...
Name.SomeProperty = NewValue;
will indeed work, because the readonly property only applies to the field named Name (of type SomeClass).
It does not in any way whatsoever propagate into the object you store in that field. In other words, you can change properties and fields in that object.
What you can't do, is this:
Name = new SomeClass(); // or some other reference to a SomeClass
(unless you use Reflection, but that is another story)
Now, you may want to have const mean "not only is this field const, but I can also only store a const type in this field", but sadly that is not possible.
Additionally, you (and I) may want some way to say "not only is this field const, but the type I chose to store in it must be immutable as well", but unfortunately there is no (current) way to get the compiler to verify this bit.
I think this is just a difference in the paradigm of what a const means. The following code won't work:
Origin = new Point();
Anywhere else in the code other than instantiation.
Within the definition of the Point object to make X and Y both const you would need to define them as such:
public class Point
{
const int X = 0;
const int Y = 0;
}
Now in your example, neither X nor Y are assignable. You only perceive this as a flaw in the language because of your C++ background. For those who have been using C# for a while, this comes perfectly natural.
readonly only means that the value of the field cannot be changed outside of constructors.
The value of the reference type is the reference. So what cannot be changed is "which" object the field references. That object instance might be mutated a lot through instance methods, properties and fields (not readonly) that the object may have.
On the other hand, the "value" of a value type (struct) is different. However, many people discourage structs that can be mutated in any way, and in case their advice is followed, this becomes less important.
Consider making the Point type immutable. If X and Y are fields, make them readonly or convert them into get-only properties. If they are properties, make them get-only (set accessor absent or private).

The constant cannot be marked static

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.

Why are const parameters not allowed in C#?

It looks strange especially for C++ developers. In C++ we used to mark a parameter as const in order to be sure that its state will not be changed in the method. There are also other C++ specific reasons, like passing const ref in order to pass by ref and be sure that state will not be changed. But why can't we mark as method parameters const in C#?
Why can't I declare my method like the following?
....
static void TestMethod1(const MyClass val)
{}
....
static void TestMethod2(const int val)
{}
....
In addition to the other good answers, I'll add yet another reason why to not put C-style constness into C#. You said:
we mark parameter as const in order to be sure that its state will not be changed in method.
If const actually did that, that would be great. Const doesn't do that. The const is a lie!
Const doesn't provide any guarantee that I can actually use. Suppose you have a method that takes a const thing. There are two code authors: the person writing the caller and the person writing the callee. The author of the callee has made the method take a const. What can the two authors assume is invariant about the object?
Nothing. The callee is free to cast away the const and mutate the object, so the caller has no guarantee that calling a method that takes a const actually will not mutate it. Similarly, the callee cannot assume that the contents of the object will not change throughout the action of the callee; the callee could call some mutating method on a non const alias of the const object, and now the so-called const object has changed.
C-style const provides no guarantee that the object will not change, and is therefore broken. Now, C already has a weak type system in which you can do a reinterpret cast of a double into an int if you really want to, so it should not be a surprise that it has a weak type system with respect to const as well. But C# was designed to have a good type system, a type system where when you say "this variable contains a string" that the variable actually contains a reference to a string (or null). We absolutely do not want to put a C-style "const" modifier into the type system because we don't want the type system to be a lie. We want the type system to be strong so that you can reason correctly about your code.
Const in C is a guideline; it basically means "you can trust me to not try to mutate this thing". That shouldn't be in the type system; the stuff in the type system should be a fact about the object that you can reason about, not a guideline to its usage.
Now, don't get me wrong; just because const in C is deeply broken doesn't mean that the whole concept is useless. What I would love to see is some actually correct and useful form of "const" annotation in C#, an annotation that both humans and compilers could use to help them understand the code, and that the runtime could use to do things like automatic paralellization and other advanced optimizations.
For example, imagine if you could "draw a box" around a hunk of code and say "I guarantee that this hunk of code performs no mutations to any field of this class" in a way that could be checked by the compiler. Or draw a box that says "this pure method mutates the internal state of the object but not in any way that is observable outside the box". Such an object could not be safely multi-threaded automatically but it could be automatically memoized. There are all kinds of interesting annotations we could put on code that would enable rich optimizations and deeper understanding. We can do way better than the weak C-style const annotation.
However, I emphasize that this is just speculation. We have no firm plans to put this sort of feature into any hypothetical future version of C#, if there even is one, which we have not announced one way or the other. It is something I would love to see, and something which the coming emphasis on multi-core computing might require, but none of this should be in any way construed to be a prediction or a guarantee of any particular feature or future direction for C#.
Now, if what you want is merely an annotation on the local variable that is a parameter that says "the value of this parameter doesn't change throughout the method", then, sure, that would be easily done. We could support "readonly" locals and parameters that would be initialized once, and a compile-time error to change in the method. The variable declared by the "using" statement is already such a local; we could add an optional annotation to all locals and parameters to make them act like "using" variables. It's never been a very high priority feature so it has never been implemented.
One of the reasons why there's no const correctness in C# is because it doesn't exist at the runtime level. Remember that C# 1.0 did not have any feature unless it was part of the runtime.
And several reasons why the CLR does not have a notion of const correctness are for example:
It complicates the runtime; besides, the JVM didn't have it either, and the CLR basically started as a project to create a JVM-like runtime, not a C++-like runtime.
If there is const correctness at the runtime level, there should be const correctness in the BCL, otherwise the feature is pretty much pointless as far as the .NET Framework is concerned.
But if the BCL requires const correctness, every language on top of the CLR should support const correctness (VB, JavaScript, Python, Ruby, F#, etc.) That's not going to happen.
Const correctness is pretty much a language feature only present in C++. So it pretty much boils down to the same argumentation as to why the CLR does not require checked exceptions (which is a Java language-only feature).
Also, I don't think you can introduce such a fundamental type system feature in a managed environment without breaking backward compatibility. So don't count on const correctness ever entering the C# world.
I believe there are two reasons C# is not const-correct.
The first is understandibility. Few C++ programmers understand const-correctness. The simple example of const int arg is cute, but I've also seen char * const * const arg - a constant pointer to constant pointers to non-constant characters. Const-correctness on pointers to functions is a whole new level of obfuscation.
The second is because class arguments are references passed by value. This means there's already two levels of constness to deal with, without an obviously clear syntax. A similar stumbling point is collections (and collections of collections, etc).
Const-correctness is an important part of the C++ type system. It could - in theory - be added to C# as something that is only checked at compile-time (it doesn't need to be added to the CLR, and wouldn't affect the BCL unless the notion of const member methods were included).
However, I believe this is unlikely: the second reason (syntax) would be quite difficult to solve, which would make the first reason (understandibility) even more of a problem.
This is possible since C# 7.2 (December 2017 with Visual Studio 2017 15.5).
For Structs and basic types only!, not for members of classes.
You must use in to send the argument as an input by reference. See:
See:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
For your example:
....
static void TestMethod1(in MyStruct val)
{
val = new MyStruct; // Error CS8331 Cannot assign to variable 'in MyStruct' because it is a readonly variable
val.member = 0; // Error CS8332 Cannot assign to a member of variable 'MyStruct' because it is a readonly variable
}
....
static void TestMethod2(in int val)
{
val = 0; // Error CS8331 Cannot assign to variable 'in int' because it is a readonly variable
}
....
const means "compile-time constant" in C#, not "readonly but possibly mutable by other code" as in C++. A rough analog of C++ const in C# is readonly, but that one is only applicable to fields. Aside from that, there is no C++-like notion of const correctness in C# at all.
The rationale is hard to tell for sure, because there are a lot of potential reasons, but my guess would be desire to keep the language simple first and foremost, and uncertain advantages of implementing this second.

Why are member constants available even if there are no instances of a its class?

1) Why are member constants available even if there are no instances of a its class?
2) Is the only reason why constant expressions need to be fully evaluated at compile time due to compiler replacing constant variable with literal value?
3) Since string is also an object, I would think the following would produce an error, but it doesn’t. Why?
class A
{
const string b = “it works”;
}
thank you
Constants (declared with const) are implicitly static - hence no need for an instance.
A const value is embedded in the assembly it's declared in, and then every time it's used, that value is copied into the calling code as well. Therefore it can't be evaluated at execution time - if you want that behaviour, use static readonly.
String literals are constant values according to the C# language specification. Basically IL has a metadata representation for strings, allowing them to be specified as constants. String constants also have other interesting properties such as interning.
One point of interest: you can declare a decimal field as const in C#, but that doesn't really have CLR support... there's no literal form. The C# compiler fakes it using the [DecimalConstant] attribute. That's why you can't use decimal as an attribute argument type.

Categories

Resources