问题
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.
回答1:
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?
回答2:
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.
回答3:
const
implies static
so there is only one instance per class.
Edit: Add Reference
回答4:
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.
回答5:
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.
回答6:
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 null
s? 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
来源:https://stackoverflow.com/questions/23529592/how-are-c-sharp-const-members-allocated-in-memory