Is it possible to initializing value of a constant value using method of another class
namespace ConsoleApplication1
{
class Program
{
const int gravit = haha.habc();//something like this
static void Main(string[] args)
{
some codes.....
}
public class haha
{
int gar = 1;
public int habc()
{
int sa = 1;
return sa;
}
}
}
}
For example like the codes above(FYI with this code I am getting Expression being assigned to ... must be constant), if not is there other method to do something similar to this.
No, that's not possible, you could use readonly field instead because constant values should be known at compile-time:
private static readonly int gravit = haha.habc();//something like this
NOTE: the habc method should be static if you want to call it that way.
Constants are values which should be known at compile time and do not change. So the ReadOnly is the option you should go with.
private readonly int gravit = haha.habc();
Related
I am partly modifying an application where I will need to set value of the following constant to the value of the environment variable if exists.
What I already have:
private const string BuildPackagePath = #"\\server\build\";
What I would like to do is:
if (Environment.GetEnvironmentVariable("EnvVar") != null)
Set the property value to = Environment.GetEnvironmentVariable("EnvVar")
else
{Keep default/assigned value}
I understand that the left side of an asignment has to be a variable. I will probably have to change the type but was just wondering if anyone could give me an idea so the structure of current code can be kept as is.
consider using a static property without setter
// evaluates Environment Variable on each call
private static string BuildPackagePath
{
get { return Environment.GetEnvironmentVariable("EnvVar") ?? #"\server\build\"; }
}
static readonly field will evaluate Environment Variable only once (but not immediately at startup When do static variables get initialized in C#?)
private static readonly string BuildPackagePath =
Environment.GetEnvironmentVariable("EnvVar") ?? #"\server\build\";
You can´t modify a constants value, that´s why it´s called constant. However you can use readonly to indicate that the member can be modified only within the constructor:
class MyClass
{
private readonly string BuildPackagePath;
public MyClass()
{
var value = Environment.GetEnvironmentVariable("EnvVar");
if(value != null) this.BuildPackagePath = value;
else this.BuildPackagePath = #"\server\build\";
}
}
Or even shorter using the null-conitional operation:
this.BuildPackagePath = value ?? #"\server\build\";
You can use "readonly" modifier instead of const. Then you can set a value of the field in a constructor of a class. For example:
class SampleClass
{
public int x;
// Initialize a readonly field
public readonly int y = 25;
public readonly int z;
public SampleClass()
{
// Initialize a readonly instance field
z = 24;
}
}
I was wondering why do instance constructor have access to static fields? If I initialize static fields via static constructors, and by mistake again initialize them through instance constructors, then the second initialization overwrites the first one. What is the idea behind making them accessible through instance constructors? (Please have a look at the simple program below to understand my point)
using System;
class Program
{
static void Main()
{
Circle C1 = new Circle(5);
Console.WriteLine("The area of the first circle is {0}", C1.CalculateArea());
}
}
class Circle
{
public static float _Pi; // Since the value of pi will not change according to circles, we have to make it static
int _Radius; // This is an instance field, whose value is different for different instances of the class
static Circle() // A static constructor initializes the static fields
{
Console.WriteLine("Static constructor executed");
Circle._Pi = 3.14F;
}
public Circle(int Radius) // An instance constructor initializes the instance fields
{
Console.WriteLine("Instance constructor executed");
this._Radius = Radius;
Circle._Pi = 2.12F; // This again initializes the value of the pi to a different value as given by the static constructor
}
public float CalculateArea()
{
return this._Radius*this._Radius*Circle._Pi;
}
}
As an example of a use case where a constructor could want access to static members is when a static field contains a counter of instances for a class. You may want a class member to get, retain (in a non-static field), and increment this counter which would be static. Any time in the future that instance will have its own unique identifier.
Example:
public class Employee {
static int NextEmployeeId; // a counter across all employees
public int EmployeeId; // this instance's employee id
public string Name; // this instance's name.
static Employee() {
Employee.NextEmployeeId = 1; // first employee gets 1.
}
public Employee(string Name) {
this.Name = Name;
this.EmployeeId = Employee.NextEmployeeId++; // take an id and increment for the next employee
}
}
Static fields are accessible from everywhere, even from constructor, or even from Main/other class. The purpose is that you will have only one static property/ field singleton for the whole app.
public class AClass()
{
public static float staticField;
public float field;
public AClass()
{
staticField = 5;
field = 6;
}
static AClass()
{
staticField = 7;
}
}
public int Main()
{
float initially = AClass.staticField; // initially this staticField is 7.
AClass aclass = new AClass(); // instantiating AClass
float localfield = aclass.field; // this field does not affect anyone. It is 6
float newStaticField = AClass.staticField; // Due to previous instantiation, the value is now 5.
}
And I agree with you that in your example it is bad. Why? Because why would you change the value of Pi, since it is already determined and fixed, there is no reason to change the value of Pi in the constructor.
You probably need to know how to design class and get to know why you want to have the static field in the first place. Here is an example of a class which does it correctly having a static field (sort of... for example, because the Key should be hidden supposedly. This is just to show you how static field is useful and ok.):
public class NewEncryptionClass()
{
public static string Key;
public NewEncryptionClass()
{
}
public NewEncryptionClass(string newKey)
{
Key = newKey; // store the key and keep it forever
}
static NewEncryptionClass()
{
Key = "key1"; // initially key is "key1"
}
public string Encrypt(string str)
{
string result = string.Empty;
result = "adlasdjalskd" + Key + "ajlajfalkjfa" + str; // do the Encryption, I just made up
return result
}
}
Here, the purpose is that if you instantiate a NewEncryptionClass, you would want to save the key, so that the next time you do the encryption, you would always use the latest key without having to specify it everytime. For ex:
public int Main()
{
string initialkey = NewEncryptionClass.Key;
string result1 = new EncryptionClass().Encrypt("encryptThis"); // using key1
// let's change the key
string result2 = new EncryptionClass("key2").Encrypt("encryptThat"); // using key2
string result3 = new EncryptionClass().Encrypt("encryptOther"); // still using key2
}
This is of course if I want to keep the latest key forever, if not, then this class design is wrong and you need to rewrite it for your purpose.
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;
}
}
I am writing following code,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ReadOnlyObject
{
class Program
{
private readonly int a = 20;
private readonly int b;
public int propa{get;private set;}
public int propb { get; private set; }
public Program(int tmp)
{
b = tmp;
}
static void Main(string[] args)
{
Program obj1 = new Program(30);
Console.WriteLine(obj1.propa); // Console.WriteLine(obj1.a);
Console.WriteLine(obj1.propb); // Console.WriteLine(obj1.b);
Console.Read();
}
}
}
After executing the above i got o/p as follows,
0
0
And when I change the code by replacing two commented statements printing direct member variables I got output as,
20
30
Why is so?
As far I know about properties they are associated with their definition in order the member variables are declared.
You have confusion about auto property, so:
private readonly int a = 20;
private readonly int b;
public int propa{get {return a; }}
public int propb { get {return b;} private set {b = value;} }
now this will print 20, 30
There are two ways to define properties in C#.
The first, the traditional way;
int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
the second, the auto-property;
public int MyProperty {get;set;}
The first contains a backing variable that you reference in the property accessor. The second implicitly creates a backing variable, because the developers of the language understood that there are a lot of cases where you just need a property!
You can put scope on the auto-property, because you might want to prevent people from setting the value, but internally to the object you should be able to update the value of it.
"As far I know about properties they are associated with their
defination in order the member variables are declated."
Just to clarify all of what you were asking, unless I am reading this statement incorrectly, you're thinking that if you declare variable a and b and the property a and property b that they'll be associated. This is an incorrect assumption.
propa and a are not associated in your example. The compiler is making them auto-implemented properties. http://msdn.microsoft.com/en-us/library/bb384054.aspx If you want propa associated with a then you'd do:
public int propa{get { return a;} }
You're not initializing either property. You also can't set the value of b from a setter if it's marked readonly. You can implement your own 'readonly' type by just not letting the value get set more than once. (Although it doesn't stay true to the constraint that it needs to be initialized in the constructor)
Try this:
private readonly int a = 20;
public int A { get { return a; } }
private int b;
private bool bInitialized = false;
public int B
{
get { return b; }
private set
{
if (bInitialized) return;
bInitialized = true;
b = value;
}
}
The way your code is written propb and propa CANNOT be set outside the scope of the class. so remove the keyword private from the set keyword
if you wrote this.propb = b in your constructor, then I think it should work more like you are expecting.
I need help about array of structs initiliazation. In a code something like below, how we can accomplish the initiliazation defined in comment ??
class structExample
{
struct state{
int previousState;
int currentState;
}
static state[] durum;
public static void main(String[] args)
{
durum = new state[5];
// how we can assign new value to durum[0].previousState = 0; doesn't work ??
}
}
}
Thanks..
The default accessibility for members in C# is private which is why the assignment statement is failing. You need to make the fields accessible by having adding internal or public to them.
struct state{
internal int previousState;
internal int currentState;
}
durum = new state[5]; -> creates only the array for 5 elements.
You need to initialize every element inside the array.