How to have program wide constant variables - c#

I have a c# program and I have some constant variables that I want to be accessible throughout the program. I won't need to change them at any point.
I have tried a static class and that worked well. I declared a 'static class' and had my variables inside as 'public static'.
The problem came when I wanted to use these unchanging variables in a case statement. Since this only accepts consts, it didn't work out too well.
The question is this: if I have a static class which does not have static variables within it, will this work just as well? This is going from public static to public const.
Thanks for your help.

Yes, consts by default are static.

It depends. Const can't be variables, they must be literals. If you're trying to assign a variable to the const such as a class you made then you have to keep it as static readonly. If you mean to assign a literal such as a number or a string then const is just fine.
A few examples:
public const int Number = 1; // this works; 1 is a literal
public const int Number = SomeClass.SomeProperty; // this does not work
public const int Number = SomeClass.SomeConst; // this works
public const SomeClass Var = new SomeClass(); // does not work
public const string Var = "test"; // this works as "test" is a literal.
If you are not using literals youre better of doing:
public static readonly SomeClass Var = new SomeClass ();
If you are using numeric literals another option is the enum which is basically a static class with some added features.
public enum MyConstants
{
VarOne, // defaults to 0
VarTwo, // defaults to next number (1)
VarThree // defaults to next number (2)
}

Related

What is the real difference between a static member and a constant in C#?

I'm learning C#,and now i'm trying to understand static members and constants.Which is the best way to declare a constant?
This way?
class Myclass
{
public const double G=9.8;
}
Or
class Myclass
{
private static double G{get;set;}
static MyClass()
{
G=9.8;
}
}
I've asked this question because,with the 2 ways i access the membre with the same code:
Console.WriteLine(Myclass.G);
constant:
Constant fields are defined at the time of declaration in the code
snippet, because once they are defined they can't be modified. By
default a constant is static, so you can't define them static from
your side.
It is also mandatory to assign a value to them at the time of
declaration otherwise it will give an error during compilation of the
program snippet. That's why it is also called a compile-time constant.
Explanation:
Consider ff. code:
void Sum(int j)
{
const int i = 9, k = 2;
const int A = i + k;
}
This will produce a result of 11, without showing any error since we already declared it at the initial point of declaration.
But how about:
void Sum(int j)
{
const int i = 9, k = 2;
//const int A = i + k;
Const int B = i + j;
}
This code snippet will take you toward a compile-time error, because there is no initialization, since it's evaluated at run time.
Points to Remember
Compile-time constant
Can't be declared static
Can't be modified or changed
Can be of any type of Access Modifier
Local scope
Needs to get initialized
Declared at the time of declaration
Static
The static keyword is used to declare a static member. If we are
declare a class as a static class then in this case all the class
members must be static too. The static keyword can be used effectively
with classes, fields, operators, events, methods and so on
effectively.
Consider ff. code:
class ReadOnly
{
static int i = 11;
public static void disp()
{
Console.WriteLine(i);
}
}
Explanation:
This code will show no error and produce a result (11), since we declared its value to be static at the time of declaration. So we can access it depending on our use in the program.
But how about this:
class ReadOnly
{
int i = 9;
public static void disp()
{
Console.WriteLine(i);
}
}
This snippet above will show an error, because we didn't declare a value for the static and we are trying to access it within a method. We can't do that.
Points to Remember:
Can't be used with indexers
Works with constructors too
By default it is private
Can be parameterized or public too
If its applied to a class then all the class members need to be static
You can read more about above explanation here: constant vs readonly vs static
Additional note for static methods.
Consider ff. code:
public class SomeClass {
public string SomeMethod() {
return "Hello, World.";
}
}
When you want to Access SomeMethod of SomeClass, you need to instantiate SomeClass first:
var some = new SomeClass();
string result = some.SomeClass(); //this will set result as "Hello, World."
Compared to a static method:
public class SomeClass {
public static string SomeMethod() {
return "Hello, World.";
}
}
When accessing SomeMethod, you don't need to instantiate SomeClass. You can access it directly by:
string result = SomeClass.SomeMethod(); //this will give "Hello, World."
Which is the best way to declare a constant?
Its not the best, its the only way: const double G = 9.8;.
Or (...) static double G { get; set; }
Thats not a constant! Constant means constant: 1 is a constant, 'c'is a constant, PI is a constant... they represent values that don't change, ever!. Your second implementation of G can change, therefore its not a constant.
Also, its important you notice that constants are known at compile time, there is no evaluation needed at runtime.
This is the reason why any reference type const (expect string which has specific compiler support through string literals) can only be initialized to null, any other option would need to be evaluated at runtime.
Its also the reason why only a finite set of value types can be declared as const too. All of them are existing types in the framework and.. surprise, surprise, they all have compiler literal constant support: 1, 'c', 9.8 or 0.25M but not 01/01/2017 (how else would the compiler know the values before runtime?).
Another interesting question you didn't make is: what about static readonly?
You can think of static readonly as "the poor man's" const. Its often used to circumvent the limitations const offers concerning what types and initializing values are allowed.
It is almost the same as a constant, but there are a few important and decisive differences:
It can change; although it is readonly, you can change it's value inside the static constructor of the declaring type. const can never change after initialized.
It is evaluated at runtime, not compile time as a true const.
Any type can be declared as a static readonly and initialized to any valid value as you would do with any regular field.
As a nittpicking side note, you shouldn't make G a constant ;). It changes, and quite a bit. G in Ecuador is different from G in the North Pole.
const variables are assigned values at time of definition.
They are available at compile time. You can even use a compile time evaluate-able expression at compile time. But once a value has been assigned to a const variable, it cannot be changed at any other time.
Using static field means the value will remain same for every user of the application, but this value can be changed by code in any of the classes, and it will change for every user of the application.
Do not use static for constants, use const only. const are by default static, and you cannot use static keyword with it.
Check this
void Main()
{
// You will not be able to change value for const variable.
Console.WriteLine(Myclass.G);
// You will be able to change value for static variable,
// and this change will impact all users of the application.
// For every user, this field will store value of 10 now.
// That will not be required or desired code behavior.
Myclass1.G = 10;
Console.WriteLine(Myclass1.G);
}
// Normal class with const field
class Myclass
{
public const double G=9.8;
}
//static class with static constructor
static class Myclass1
{
public static double G{get;set;}
static Myclass1()
{
G=9.8;
}
}
Read More
Here you are talking about two different things, and this is their definition from MSDN:
1- static modifier: To declare a static member, which belongs to the type itself rather than to a specific object. The static modifier can be used with classes, fields, methods, properties, operators, events, and constructors, but it cannot be used with indexers, finalizers, or types other than classes.
2- const keyword: To declare a constant field or a constant local. Constant fields and locals aren't variables and may not be modified. Constants can be numbers, Boolean values, strings, or a null reference. Don’t create a constant to represent information that you expect to change at any time.
So a static member is defined for a Class (for all its instances, and that's why you can access it directly from the name of the Class) but can be modified. a const field of class can not be modified.

Alternative for Static Field

Is there any alternative present for Static Field in C# as static field never garbage collected?
If I want to declaure the number of strings, constants which I want to use throughout the program, I am finding a way for that.
You can use a const but it has to be a value.
public class Foo
{
public const string Bar = "Bar";
}
See https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
As an addition to Richard Schneiders answer, sometimes you can't use const (the compiler should know the const value at the compiling time), but want to provide constant like behaviour. In that case readonly is the choice:
public class Foo {
// Settings should be read and then preserved intact
public static readonly String Settings = File.ReadAllText(#"C:\MySettings.txt");
...
}
You can Use Const for this.
Const is a reserved word. It allows us to specify that a value is invariant and must not be modified after compile-time. Const values, like const strings, help us simplify and optimize programs.
Eg:
public static class Constants
{
public const string Name = "abc";
}
https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx

Not sure which way to declare my constants in C#

I would like to know how to declare a "global" variable for a class. That is I want that this variable is available everywhere just in this class and not in the other classes.
What is the best form to declare them? or when do I use each of these forms?
I would like to have it OO.
1st Form:
enter code here
private const string _Column1= "Names";
private const string _Column2= "Numbers";
private const string _Column3= "Alarms";
2nd Form:
private enum enumColumnNames
{
Names, // integer value = 0
Numbers, // 1
Alarms, // 2
};
3rd Form:
internal sealed class clsColumnNames
{
public static readonly clsColumnNames Column1 = new clsColumnNames("Names");
public static readonly clsColumnNames Column2 = new clsColumnNames("Numbers");
public static readonly clsColumnNames Column3 = new clsColumnNames("Alarms");
private clsColumnNames(string value)
{ Value = value;
}
public string Value { get; private set; }
}
4th Form:
internal sealed class clsColumnNames
{
public static readonly string Column1 = "Names";
public static readonly string Column2= "Numbers";
public static readonly string Column3= "Alarms";
}
Thanks!
Cis
private enum enumColumnNames
{
Names, // integer value = 0
Numbers, // 1
Alarms, // 2
};
And as long as the string value is equal to the enum name you can use
enumColumnNames.Names.ToString() will produce "Names"
static class ColumnNames
{
public const string Names = "Names";
public const string Number = "Numbers";
public const string Alarms = "Alarms";
}
Since these are constants, I would recommend the enum approach. As mentioned by Amorphis, this will aloow you to get the literal value viw .ToString(). This also allows you to pass around your strings as a parameter boxed to the given values by using the enum type as a parameter, rather than a string which may or may not be one of the given values. There are some ways around this (such as converting an out-of-range int) but it's still less error-prone than passing raw strings everywhere.
Not also, however, that whenever you have front-facing text, you should use a Resource (.resx), because this allows you to adjust how the strings show up depending on the language settings of the machine running your code. If any of these strings are ever to be seen by a user, use resources!
The 1st form is the best for the following reasons:
Simplest
Less typing
The 2nd form will just result in lots of needless extra code/typing (i.e., enumColumnNames.Names.ToString(), just to get the value of your variable. I've already worn my fingers out just typing that once).
For the 3rd form, let's break it down:
Making the class internal isn't really changing anything since your variables are private
Making the class sealed just means the class cannot be inherited from; again, this is not changing anything since your variables are private
Making your variables static just means that they won't show up in an object of the class; again, not really doing anything
Making your variables readonly just means that they can only be set in a constructor
There is no point in having a property for a variable that you intend to be constant; Properties are generally used to make sure that a variable is being set/gotten properly
And for the 4th form, same gripes as with the 3rd, just minus the last gripe.
EDIT:
Since these particular variables you are asking about are supposed to be column names, I would actually recommend Amorphis' answer (sorry Amorphis, I don't have enough rep to upvote your answer just yet). If your global variables are unrelated to each other (i.e., a variable for the name of a webpage vs. a variable for the number of characters allowed in a text field are nice and dissimilar), then you ought to use the first form.

Pass a variable from one file to another c#

I have two .cs files (Hex2Bin.cs and Program.cs) and I want to pass the variable end_addr from Program.cs to Hex2Bin.cs
My code in Program.cs:
class Program
{
enum to_exit {
exit_ok = 0,
exit_invalid_args,
exit_to_few_args,
exit_invalid_input_file,
exit_invalid_args_file,
exit_permission_denied,
exit_unexpected_eof
};
// class value holders
static String args_file_name = "";
static String in_u1_name = "";
static String in_u22_name = "";
static String out_name = "";
static short end_addr = 0x0000; // 4-digit Hexadecimal end address
static Byte[] version_code = { 0, 0, 0, 0 }; // 3 bytes version, 1 for extra info
}
Is there anyway I could do this? I know how to do it in c, but I'm very new to c#. Thanks.
C# doesn't work like C with respect to static variables. You can make the variable end_addr available outside the Program class by making it a public field. By default, fields are private.
public static end_addr = 0x0000;
And then it can be accessed like so:
var x = Program.end_addr;
However, I would recommend that you spend a little more time familiarizing yourself with C# idioms and conventions. It seems like your still thinking about C# in terms of C, and they are very different.
if you declare the variable like this:
public static short end_addr = 0x0000;
then from another class you can use it like this:
Program.end_addr
but don't do this, is not object oriented!
if your class Hex2Bin is used/invoked by the Main method of Program class, you should be able to pass your variables as input parameters of the methods you call or set them as properties of the classes/objects you use...
It's enough to mark end_addr as public like so
public static short end_addr = 0x0000;
Then you can access it from anywhere like this
Program.end_addr
It's a better practice though to use properties rather than fields for exposing data.
// Property
public static short end_addr { get; private set; }
// Constructor
public Program()
{
// Initialize property value.
end_addr = 0x0000;
}
You're talking about 'files' but what you really want to do is to pass data from your program's entry point (Program.cs) to a an object of a class (or method of static class) that will process the data, am I right?
If so, this should be pretty simple. You either have to modify your Program.cs and create an instance of the class (the one from Hex2Bin.cs) like this
...
Hex2Bin hex2bin = new Hex2Bin( end_addr );
...
I assume that the Hex2Bin is as follows:
public class Hex2Bin
{
private short endAddress;
public Hex2Bin( short endAddress )
{
this.endAddress = endAddress;
}
}
this will allow you to use the value of end_addr from Program.cs
Another approach is to pass it directly to the method that will make use of it:
Hex2Bin.Method(end_addr);
and in the Hex2Bin file:
public static void Method(short endAddress)
{
//... do the work here
}
Given your background in C, I think you may be mixing runtime with compile time issues.
However, in Hex2Bin.cs, you can create a static method that updates a static variable.
class Hex2Bin
{
static short end_addr = 0x0000;
static void updateEndAddr(short endAddr)
{
end_addr = endAddr;
}
}

Is it possible to have a getter for a const?

Just curious, is there a way to have a getter for a constant variable? I have a sort of internal version number to ensure that two versions of a library are still speaking the same language, but I'd like the programmer to be able to check what version they're using. Right now I use:
private const Int16 protocol_version = 1;
public Int16 ProtocolVersion => protocol_version;
But I'd prefer to do it with just the const if there's a way.
You could declare a property with only a get accessor (without even declaring the set accessor, not even private):
private const Int16 protocol_version = 1;
public Int16 ProtocolVersion => protocol_version;
This is not the same as defining a constant only: the constant would be resolved at compile time, so if you update the library without recompiling the dependent program, the program would still see the "old" value. Consider this example:
// The class library
using System;
namespace MyClassLibrary {
public class X {
public const Int16 protocol_version = 1;
public Int16 ProtocolVersion => protocol_version;
}
}
// The program
using System;
using MyClassLibrary;
class Program {
static void Main(string[] args) {
var x = new X();
Console.WriteLine($"Constant: {X.protocol_version0}");
Console.WriteLine($"Getter: {x.ProtocolVersion}");
}
}
Now, compile the first time and execute the program. You will see
Constant : 1
Getter : 1
Then, modify protocol_version to 2, and recompile the class library only, without recompiling the program, then put the new class library in the program folder and execute it. You will see:
Constant : 1
Getter : 2
The fact is that if it's just a constant, the value is replaced at compile time.
I think that what you are actually looking for is a static readonly variable: in that way, you will avoid the compile-time const replacement, and the variable will not be modifiable after initialization:
public static readonly Int16 protocol_version = 1;
You have to keep in mind the reason for the existance of getters/setters. It is to control access to an encapsulated variable, specifically to control how a variable is changed and who can change it. Since a const is set only once and remains read-only on runtime there is no reason to create a property for it. Setting the constant to public is completely acceptable since it is not a private variable that needs to be protected.
If you really... really want to make it a property then just define it as a readonly property, skip the setter entirely:
public Int16 ProtocolVersion => protocol_version;
But just so we are clear, I would say normally you would have public constants with the same coding style as properties:
public const Int16 ProtocolVersion = 1
Just do:
public const Int16 protocol_version = 1;
This will provide a public getter as a const cannot have a setter.
Constants cannot be reassigned, hence why they are called constant therefore just make protocol_version public
private const Int16 protocol_version = 1;

Categories

Resources