c# Consts in a public class - c#

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.

Related

Error using static string in Attribute. Microsoft.Net.Http.Headers.HeaderNames not a const anymore

In a new ASP.NET Core 5 project, when defining a Header Attributer filter for Swashbuckle:
[RequestHeaderMatchesMediaType(
Microsoft.Net.Http.Headers.HeaderNames.Accept, "mytypename")]
Exception:
CS0182 An attribute argument must be a constant expression
Caused by dotnet HeaderNames source code:
public static readonly string Accept = "Accept";
Attributes complilation demand a const, so I've copied the original aspnet Microsoft.Net.Http.Headers constants.
There is a discussion about why the change was made on dotnet aspnet core github #12439, but the question I have is:
How do I use a static readonly in an attribute?
As already mentioned in the comments, you cannot use static readonly fields in attributes. The reason for this is that attributes need compile-time constant values, while static readonly fields are only created at run-time.
The linked issue (and there are others for similar changes) already discuss why they made the change from constant values to static fields. In the end, the reason is irrelevant to you in this situation: You want to use the header name in the attribute.
The only solution here is to simply copy the value, and you can do that directly like this:
[RequestHeaderMatchesMediaType("Accept", "mytypename")]
If you end up doing a check like this repeatedly, then it may make sense to introduce a constant yourself, so that you can reuse the same value, and e.g. be safe against misspellings in some cases. Introducing a constant also allows you to use IDE tools to find its usages. However, defining a constant will not impact the result. During compilation, constant values will be copied in and the original const declaration “disappears”.
public class Constants
{
public const AcceptHeaderName = "Accept";
public const MyTypeName = "mytypename";
}
[RequestHeaderMatchesMediaType(Constants.AcceptHeaderName, Constants.MyTypeName)]

Is there a functional difference between Const and Static Readonly field value? [duplicate]

I've read around about const and static readonly fields. We have some classes which contain only constant values. They are used for various things around in our system. So I am wondering if my observation is correct:
Should these kind of constant values always be static readonly for everything that is public? And only use const for internal/protected/private values?
What do you recommend? Should I maybe even not use static readonly fields, but rather use properties maybe?
public static readonly fields are a little unusual; public static properties (with only a get) would be more common (perhaps backed by a private static readonly field).
const values are burned directly into the call-site; this is double edged:
it is useless if the value is fetched at runtime, perhaps from config
if you change the value of a const, you need to rebuild all the clients
but it can be faster, as it avoids a method call...
...which might sometimes have been inlined by the JIT anyway
If the value will never change, then const is fine - Zero etc make reasonable consts ;p Other than that, static properties are more common.
I would use static readonly if the Consumer is in a different assembly. Having the const and the Consumer in two different assemblies is a nice way to shoot yourself in the foot.
A few more relevant things to be noted:
const int a
must be initialized.
initialization must be at compile time.
readonly int a
can use a default value, without initializing.
initialization can be done at run time (Edit: within constructor only).
This is just a supplement to the other answers. I will not repeat them (now four years later).
There are situations where a const and a non-const have different semantics. For example:
const int y = 42;
static void Main()
{
short x = 42;
Console.WriteLine(x.Equals(y));
}
prints out True, whereas:
static readonly int y = 42;
static void Main()
{
short x = 42;
Console.WriteLine(x.Equals(y));
}
writes False.
The reason is that the method x.Equals has two overloads, one that takes in a short (System.Int16) and one that takes an object (System.Object). Now the question is whether one or both apply with my y argument.
When y is a compile-time constant (literal), the const case, it becomes important that there does exist an implicit conversion from int to short provided that the int is a constant, and provided that the C# compiler verifies that its value is within the range of a short (which 42 is). See Implicit constant expression conversions in the C# Language Specification. So both overloads have to be considered. The overload Equals(short) is preferred (any short is an object, but not all object are short). So y is converted to short, and that overload is used. Then Equals compares two short of identical value, and that gives true.
When y is not a constant, no implicit conversion from int to short exists. That's because in general an int may be too huge to fit into a short. (An explicit conversion does exist, but I didn't say Equals((short)y), so that's not relevant.) We see that only one overload applies, the Equals(object) one. So y is boxed to object. Then Equals is going to compare a System.Int16 to a System.Int32, and since the run-time types do not even agree, that will yield false.
We conclude that in some (rare) cases, changing a const type member to a static readonly field (or the other way, when that is possible) can change the behavior of the program.
One thing to note is const is restricted to primitive/value types (the exception being strings).
Static Read Only:
The value can be changed through a static constructor at runtime. But not through a member function.
Constant:
By default static. A value cannot be changed from anywhere (constructor, function, runtime, etc. nowhere).
Read Only:
The value can be changed through a constructor at runtime. But not through a member function.
You can have a look at my repository: C# property types.
The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for runtime constants
From this short and clear MSDN reference.
const and readonly are similar, but they are not exactly the same.
A const field is a compile-time constant, meaning that that value can be computed at compile-time. A readonly field enables additional scenarios in which some code must be run during construction of the type. After construction, a readonly field cannot be changed.
For instance, const members can be used to define members like:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
Since values like 3.14 and 0 are compile-time constants. However, consider the case where you define a type and want to provide some pre-fab instances of it. E.g., you might want to define a Color class and provide "constants" for common colors like Black, White, etc. It isn't possible to do this with const members, as the right hand sides are not compile-time constants. One could do this with regular static members:
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}
But then there is nothing to keep a client of Color from mucking with it, perhaps by swapping the Black and White values. Needless to say, this would cause consternation for other clients of the Color class. The "readonly" feature addresses this scenario.
By simply introducing the readonly keyword in the declarations, we preserve the flexible initialization while preventing client code from mucking around.
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}
It is interesting to note that const members are always static, whereas a readonly member can be either static or not, just like a regular field.
It is possible to use a single keyword for these two purposes, but this leads to either versioning problems or performance problems. Assume for a moment that we used a single keyword for this (const) and a developer wrote:
public class A
{
public static const C = 0;
}
and a different developer wrote code that relied on A:
public class B
{
static void Main() => Console.WriteLine(A.C);
}
Now, can the code that is generated rely on the fact that A.C is a compile-time constant? I.e., can the use of A.C simply be replaced by the value 0? If you say "yes" to this, then that means that the developer of A cannot change the way that A.C is initialized -- this ties the hands of the developer of A without permission.
If you say "no" to this question then an important optimization is missed. Perhaps the author of A is positive that A.C will always be zero. The use of both const and readonly allows the developer of A to specify the intent. This makes for better versioning behavior and also better performance.
My preference is to use const whenever I can, which, as mentioned in previous answers, is limited to literal expressions or something that does not require evaluation.
If I hit up against that limitation, then I fallback to static readonly, with one caveat. I would generally use a public static property with a getter and a backing private static readonly field as Marc mentions here.
Const: Constant variable values have to be defined along with the declaration and after that it won't change.const are implicitly static, so without creating a class instance we can access them. This has a value at compile time.
ReadOnly: We can define read-only variable values while declaring as well as using the constructor at runtime. Read-only variables can't access without a class instance.
Static readonly: We can define static readonly variable values while declaring as well as only through a static constructor, but not with any other constructor. We can also access these variables without creating a class instance (as static variables).
Static readonly will be better choice if we have to consume the variables in different assemblies. Please check the full details in the below blog post:
Const Strings – a very convenient way to shoot yourself in the foot
A static readonly field is advantageous when exposing to
other assemblies a value that might change in a later version.
For instance, suppose assembly X exposes a constant as follows:
public const decimal ProgramVersion = 2.3;
If assembly Y references X and uses this constant, the value 2.3
will be baked into assembly Y when compiled. This means that
if X is later recompiled with the constant set to 2.4, Y will still
use the old value of 2.3 until Y is recompiled. A static
readonly field avoids this problem.
Another way of looking at this is that any value that might
change in the future is not constant by definition, and so should
not be represented as one.
Const: Const is nothing but "constant", a variable of which the value is constant but at compile time. And it's mandatory to assign a value to it. By default a const is static and we cannot change the value of a const variable throughout the entire program.
Static ReadOnly: A Static Readonly type variable's value can be assigned at runtime or assigned at compile time and changed at runtime. But this variable's value can only be changed in the static constructor. And cannot be changed further. It can change only once at runtime
Reference: c-sharpcorner
There is a minor difference between const and static readonly fields in C#.Net
const must be initialized with value at compile time.
const is by default static and needs to be initialized with constant value, which can not be modified later on.
It can not be used with all datatypes. For ex- DateTime. It can not be used with DateTime datatype.
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public static readonly string Name = string.Empty; //No error, legal
readonly can be declared as static, but not necessary. No need to initialize at the time of declaration. Its value can be assigned or changed using constructor once. So there is a possibility to change value of readonly field once (does not matter, if it is static or not), which is not possible with const.
const:
value should be given upon declaration
compile time constant
readonly:
value can be given upon declaration or during runtime using constructors.The value may vary depend upon the constructor used.
run time constant
A const (being determined at compile-time) can be used in cases where a readonly static can't, like in switch statements, or attribute constructors. This is because readonly fields are only resolved at run-time, and some code constructs require compile time assurance. A readonly static can be calculated in a constructor, which is often an essential and useful thing. The difference is functional, as should be their usage in my opinion.
In terms of memory allocation, at least with strings (being a reference type), there seems to be no difference in that both are interned and will reference the one interned instance.
Personally, my default is readonly static, as it makes more semantic and logical sense to me, especially since most values are not needed at compile time. And, by the way, public readonly statics are not unusual or uncommon at all as the marked answer states: for instance, System.String.Empty is one.
Another difference between declaring const and static readonly is in memory allocation.
A static field belongs to the type of an object rather than to an instance of that type. As a result, once the class is referenced for the first time, the static field would "live" in the memory for the rest of time, and the same instance of the static field would be referenced by all instances of the type.
On the other hand, a const field "belongs to an instance of the type.
If memory of deallocation is more important for you, prefer to use const. If speed, then use static readonly.
Use const if you can provide a compile-time constant:
private const int Total = 5;
Use static readonly if you need your value evaluated during run-time:
private static readonly int GripKey = Animator.StringToHash("Grip");
This will give a compile error because it is impossible to get the value at compile-time.
private const int GripKey = Animator.StringToHash("Grip");
Constants are like the name implies, fields which don't change and are usually defined statically at compile time in the code.
Read-only variables are fields that can change under specific conditions.
They can be either initialized when you first declare them like a constant, but usually they are initialized during object construction inside the constructor.
They cannot be changed after the initialization takes place, in the conditions mentioned above.
Static read-only sounds like a poor choice to me since, if it's static and it never changes, so just use it public const. If it can change then it's not a constant and then, depending on your needs, you can either use read-only or just a regular variable.
Also, another important distinction is that a constant belongs to the class, while the read-only variable belongs to the instance!
Const
Can be applied only for fields. Value should be in code compile time.
Suited for removing magic "strings","int/double", (primitive types) etc across the code which is known already before compiling the code.
After compiling the value will be placed all over the compiled code wherever constant is used. So if you have a huge string used many places, then watch out before making it const. consider using static read only.
Static read only
Static read only be applied for fields/props and static can be used for methods.
(on side note)When static is applied to methods, the complied code does not pass the 'this' parameter to the method and hence you cannot access the instance data of the object.
Suitable for values which may change after compiling the code. Like values initialized from configuration, during startup of application etc.
After compiling the code, the ref to value is used in IL code and may be slower compared to using const, but compiled code is small
During Refactoring, All const can be safely converted to Static read only, but not vise versa as we have seen above when converted code may break as some static readonly variable could be initialized in constructors.
There is one important question, that is not mentioned anywhere in the above answers, and should drive you to prefer "const" especially for basic types like "int", "string" etc.
Constants can be used as Attribute parameters, static readonly field not!
Azure functions HttpTrigger, not using HttpMethods class in attribute
If only microsoft used constants for Http's GET, POST, DELETE etc.
It would be possible to write
[HttpTrigger(AuthorizationLeve.Anonymous, HttpMethods.Get)] // COMPILE ERROR: static readonly,
But instead I have to resort to
[HttpTrigger(AuthorizationLeve.Anonymous, "GET")] // STRING
Or use my own constant:
public class HttpConstants
{
public const string Get = "GET";
}
[HttpTrigger(AuthorizationLeve.Anonymous, HttpConstants.Get)] // Compile FINE!
One additional difference that I don't believe is mentioned above:
const and static readonly values don't get CodeLens applied to them in the Visual Studio IDE.
static get only properties DO get CodeLens applied to them.
I consider the addition of CodeLens to be quite valuable.
Note: Currently using Visual Studio 2022.
Const, readonly, static readonly - keywords that perform a similar action but have an important difference:
• Const - is a variable whose value is constant and is assigned at compile time. You must assign a value to it. The default constants are static, and we cannot change the value of the const variable throughout the program.
• Readonly - means a value that we can change at run time, or we can assign it at run time, but only through a non-static constructor.
• Static readonly - values ​​can be assigned at run time or assigned at compile time and changed at run time. But the value of this variable can be changed only in the static constructor. And cannot be changed further. It can only be changed once during execution.
Examples you can find here - https://www.c-sharpcorner.com/UploadFile/c210df/difference-between-const-readonly-and-static-readonly-in-C-Sharp/

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.

Const field or get property

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;
}
}

Why can't I access a public const in c#?

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

Categories

Resources