What's the difference between the first and second definitions?
//1
private static string Mask
{
get { return "some text"; }
}
//2
private const string Mask = "some text";
Which benefits has the first and the second approach?
As long as they are private they will probably be optimized to more or less the same code. The re is another story if they are public and used from other assemblies.
const variables will be substitued/inlined in other assemblies using the const expression. That means that you need to recompile every assembly using the const expression if you change the expression. On the other hand the property solution will give you a method call overhead each time used.
Basically const fields value evaluated at compile time and initiailized at declaration only.
Also important point that they are stored in the assembly metadata so there is could be a problem when you distributing assembly across the customers and then give them an updated version, so they need to recompile assemblies which referencing const to pick up an updated value as well.
In few words static field is something like a global variable which is accessible without instantiating any instance of underlying type, but in your case private access modifieds makes it unaccessible out of the type where it declared.
EDIT:
Very good Community Wiki post regarding constants: Referencing constants across assemblies (post no longer exists as of June 2013.)
const is a keyword of the language. 1s defined, your not allowed to change it down the line. Yes the property also depicts the same story, but it can have much more structure in it.
In const, Once initialize can not modify. get can also not modify.
But when you have a scenario where you need different values every time you call Or, your value depends on any other function call, get will be used.
private static string Mask
{
get
{
var someOtherMethodText = SomeOtherMethodText();
return "some text" + someOtherMethodText;
}
}
Related
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
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.
I have something like this:
namespace MyNamespace {
public partial class MyClass: UserControl {
public static const String MYCONST = "MyConstant";
I can't see MYCONST from anywhere even from MyClass, why ?
A constant is available in a static context anyway, so remove the static keyword and you'll be fine.
MSDN docs:
The static modifier is not allowed in a constant declaration.
The reason is that a constant's value has to be fully evaluated at compile time and what the compiler does is that it takes that value and replaces all the usages of the constant throughout the code with the constant value.
That is why it sometimes can be better to use a public readonly value instead as the compiler does not replace the usages with the value but instead links to the readonly variable. This is especially something to think about when using constants from another assembly since you might not update all assemblies at once and you might end up with assmblies using the old constant value.
Ref: http://msdn.microsoft.com/en-us/library/e6w8fe1b(v=vs.80).aspx
According to the documentation for const
The static modifier is not allowed in a constant declaration.
Remove the static keyword from your constant and it should work.
Edit
Note that a const will be available as a class member, just like when you have static for non const variables. But for const the static is implicit and not allowed to type out.
What the heck kind of compiler are you using?
In general, making constants public is not a good idea. They behave differently from readonly variables, their literal value gets compiled into the IL. Which is a problem if the const is declared in another assembly. You could, say, ship a bug fix for an assembly that modified the const value. The other assemblies in your product will however continue to use the old value. The jitter won't complain about the mismatch. Not good.
A public const is only okay if it is a 'manifest' constant. Like Math.PI, only running the code in another universe could produce unexpected results. A product or company name is already pretty risky.
It should be accessible as MyNamespace.MyClass.MYCONST
You have a compile error in your code.
When I compile your code I get this:
The constant 'MyNamespace.MyClass.MYCONST' cannot be marked static
See the motivation for this error on Eric Lippert's blog:
Don't repeat yourself; consts are already static
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 have a class below:
I want to access these default strings but C# compiler doesn't like combining Const to create a Const.
public class cGlobals
{
// Some Default Values
public class Client
{
public const string DatabaseSDF = "database.sdf";
public const string DatabaseDir = "database";
public const string DatabaseFullLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
DatabaseDir);
public const string DataSource = Path.Combine(DatabaseDir, DatabaseSDF);
}
}
Is there a better way instead of hard coding the strings? I want to make use of the Special Folders and Path.Combine.
Thanks
You must use static readonly instead of const, since const have to be a constant at compile-time.
Also, constants will actually be compiled into assemblies that are using them, so if you are referencing those fields from other assemblies you would have to recompile them if you changed the constants. This doesn't happen with static readonly fields. So either way, it's a better idea :)
I actually asked about this a while ago and I would recommend reading it and the accepted answer: static readonly vs const.
For a variable to be declared const, the assigned value has to be a compile-time constant; to use the result of a method call you need to change your variable declaration:
public static readonly string DataSource = ...;
If you think about it, this isn't a compile-time constant, in that it will give different results based on which OS you run it on. It's constant within a single execution but not a "general" constant.
Just to add to the other correct answers: a constant should logically be something that is unchanging for all time and all places. Things like the number of eggs in a dozen, the atomic number of lead, and so on. Values that change over time, like the number of countries in the European Union, or the price of a troy ounce of gold in Australian dollars, should not be modeled as constants.
In your case, the value is not logically constant for all time and all places, so don't try to use a constant.
You can use readonly instead of const.
You could also look at using app.config to store your configuration settings.
I'm afraid you will have to use
static public readonly string DatabaseFullLocation = Path.Combine(/* ... */);
instead;
Personally, I would not hard code the strings at all.
I'd put them into appSettings.
Why? Well, if you need to change those values, you'll need to recompile your code. Putting them in as appSettings will allow you to just change your config file.
You can still provide an accessor through your class.
public string DatabaseSDF
{
get
{
return System.Configuration.ConfigurationManager.AppSettings["DatabaseSDF"];
}
}
Best of both worlds, imo.
const types have to be identified at compile time, in your code you're
trying to call Path.Combine at
run-time to figure out the actual
path. And you cannot update const at
runtime.
In Application Settings you can keep these kind of Constants .
In project properties ,select the settings tab. In the grid you can set your constants.
You can get as well as set these variables even during runtime.
Message.show(My.Settings.YourVariable); //you will get the value
and set by
My.Settings.YourVariable="Vibin";
My.Settings.Save()
I think this is one of the best way.
Define a class lets say GetDirectory.
Make all methods static.
Define a class for constants.
delcate all variables with --> public static readonly string Name_Of_Var = "Any value"
From GetDirectory methods - Define the code for folder you need to access
Ex: Path.Combine(GetFolderPath(Environment.SpecialFolder. "Select name of folder"), name of constants)
Done.