Constant class variable in c# [duplicate] - c#

This question already has answers here:
How to implement a read only property
(8 answers)
What is the difference between const and readonly in C#?
(30 answers)
Closed 1 year ago.
I want to declare a variable in my class, that cannot be changed later like this:
obj myobj=new obj()
myobj.CONSTANT_VAR="Changed value" //ERROR!!
...but whose value can be accessed like:
Console.WriteLine(myobj.CONSTANT_VAR)
I tried the following:
public class obj{
public int a, b;
public const string CONSTANT_VAR;
public obj(int x,int y){
a=x;
b=y;
CONSTANT_VAR=1/(a*((""+a).Length)+3/(b*((""+b).Length)).ToString();
}
public int do(){
return this.a+this.b-(CONSTANT_VAR).Length;
}
}
class DriverClass(){
static void Main(){
obj myObj=new obj(2,3);
myObj.a=34;
myObj.b=35;
myObj.CONSTANT_VAR="changed ur string lol"; //i want it to print error
Console.WriteLine(CONSTANT_VAR); //no error
Console.WriteLine(myObj.add());
}
}
But i instead get the following error message:
constants must have a value assigned
But i dont want to assign it a value beforehand.....
What do i do?

You're looking for read-only fields or properties, not const which is for genuine global constants.
I'd recommend avoiding public fields entirely, and instead using properties - so in this case you'd want a get-only property. Following .NET naming conventions, you'd have something like:
public class Obj
{
public int A { get; set; }
public int B { get; set; }
public string ConstantVar { get; }
public Obj(int x, int y)
{
A = x;
B = y;
ConstantVar = /* complex expression */
}
public int Do() => A + B - ConstantVar.Length;
}

You can use Readonly, it gives you option to set the value once and can not be changed later.
public class obj(){
public int a, b;
public readonly string CONSTANT_VAR;
public obj(int x,int y){
a=x;
b=y;
CONSTANT_VAR=1/(a*((""+a).Length)+3/(b*((""+b).Length)).ToString();
}
public int do(){
return this.a+this.b-(CONSTANT_VAR).Length;
}
}
class DriverClass(){
static void Main(){
obj myObj=new obj(2,3);
myObj.a=34;
myObj.b=35;
myObj.CONSTANT_VAR="changed ur string lol"; //i want it to print error
Console.WriteLine(CONSTANT_VAR); //no error
Console.WriteLine(myObj.add());
}
}

Related

Dictionary that points to getters/setters [duplicate]

This question already has answers here:
Accessing object property as string and setting its value
(11 answers)
Closed 11 months ago.
Is it possible to make a dictionary that points to getters & setters?
For example:
public class test
{
public Dictionary<string, int> pointer = new Dictionary<string,int>()
{
{ "a", a }
}; // the goal is to do pointer["a"] = someInt or print(pointer[a])
public int a { get { return b;} set { b = 2; } }
public int b;
}
Odds are you are not actually trying to put getters and setters in a dictionary, and that you are trying to access properties by their names. This is easily possible through Reflection. If that is what your question is about you should mark this as duplicate and close the question.
But, the answer to your actual question is yes. It is possible to make a dictionary that points to getters and setters. You will need to use some lambda programming. Here is one way to do it:
public class test
{
public Dictionary<string, GetSet<int>> pointer;
public test()
{
pointer = new Dictionary<string, GetSet<int>>()
{
{ "a", new(()=>a,i=>a = i) }
};
}
public int a { get { return b; } set { b = 2; } }
public int b;
}
public class GetSet<T>
{
private readonly Func<T> _get;
private readonly Action<T> _set;
public GetSet(Func<T> get, Action<T> set)
{
_get = get;
_set = set;
}
public T Get() => _get();
public void Set(T value) => _set(value);
}
Usage:
var test = new test();
var property = test.pointer["a"];
var value = property.Get();//returns the value of test.a
property.Set(3);//sets test.a to 3

C# constructors sharing code and then referencing properties already set [duplicate]

I have two constructors which feed values to readonly fields.
public class Sample
{
public Sample(string theIntAsString)
{
int i = int.Parse(theIntAsString);
_intField = i;
}
public Sample(int theInt) => _intField = theInt;
public int IntProperty => _intField;
private readonly int _intField;
}
One constructor receives the values directly, and the other does some calculation and obtains the values, then sets the fields.
Now here's the catch:
I don't want to duplicate the
setting code. In this case, just one
field is set but of course there may
well be more than one.
To make the fields readonly, I need
to set them from the constructor, so
I can't "extract" the shared code to
a utility function.
I don't know how to call one
constructor from another.
Any ideas?
Like this:
public Sample(string str) : this(int.Parse(str)) { }
If what you want can't be achieved satisfactorily without having the initialization in its own method (e.g. because you want to do too much before the initialization code, or wrap it in a try-finally, or whatever) you can have any or all constructors pass the readonly variables by reference to an initialization routine, which will then be able to manipulate them at will.
public class Sample
{
private readonly int _intField;
public int IntProperty => _intField;
private void setupStuff(ref int intField, int newValue) => intField = newValue;
public Sample(string theIntAsString)
{
int i = int.Parse(theIntAsString);
setupStuff(ref _intField,i);
}
public Sample(int theInt) => setupStuff(ref _intField, theInt);
}
Before the body of the constructor, use either:
: base (parameters)
: this (parameters)
Example:
public class People: User
{
public People (int EmpID) : base (EmpID)
{
// Add more statements here.
}
}
I am improving upon supercat's answer. I guess the following can also be done:
class Sample
{
private readonly int _intField;
public int IntProperty
{
get { return _intField; }
}
void setupStuff(ref int intField, int newValue)
{
//Do some stuff here based upon the necessary initialized variables.
intField = newValue;
}
public Sample(string theIntAsString, bool? doStuff = true)
{
//Initialization of some necessary variables.
//==========================================
int i = int.Parse(theIntAsString);
// ................
// .......................
//==========================================
if (!doStuff.HasValue || doStuff.Value == true)
setupStuff(ref _intField,i);
}
public Sample(int theInt): this(theInt, false) //"false" param to avoid setupStuff() being called two times
{
setupStuff(ref _intField, theInt);
}
}
Here is an example that calls another constructor, then checks on the property it has set.
public SomeClass(int i)
{
I = i;
}
public SomeClass(SomeOtherClass soc)
: this(soc.J)
{
if (I==0)
{
I = DoSomethingHere();
}
}
Yeah, you can call other method before of the call base or this!
public class MyException : Exception
{
public MyException(int number) : base(ConvertToString(number))
{
}
private static string ConvertToString(int number)
{
return number.toString()
}
}
Constructor chaining i.e you can use "Base" for Is a relationship and "This" you can use for same class, when you want call multiple Constructor in single call.
class BaseClass
{
public BaseClass():this(10)
{
}
public BaseClass(int val)
{
}
}
class Program
{
static void Main(string[] args)
{
new BaseClass();
ReadLine();
}
}
When you inherit a class from a base class, you can invoke the base class constructor by instantiating the derived class
class sample
{
public int x;
public sample(int value)
{
x = value;
}
}
class der : sample
{
public int a;
public int b;
public der(int value1,int value2) : base(50)
{
a = value1;
b = value2;
}
}
class run
{
public static void Main(string[] args)
{
der obj = new der(10,20);
System.Console.WriteLine(obj.x);
System.Console.WriteLine(obj.a);
System.Console.WriteLine(obj.b);
}
}
Output of the sample program is
50 10 20
You can also use this keyword to invoke a constructor from another constructor
class sample
{
public int x;
public sample(int value)
{
x = value;
}
public sample(sample obj) : this(obj.x)
{
}
}
class run
{
public static void Main(string[] args)
{
sample s = new sample(20);
sample ss = new sample(s);
System.Console.WriteLine(ss.x);
}
}
The output of this sample program is
20
Error handling and making your code reusable is key. I added string to int validation and it is possible to add other types if needed. Solving this problem with a more reusable solution could be this:
public class Sample
{
public Sample(object inputToInt)
{
_intField = objectToInt(inputToInt);
}
public int IntProperty => _intField;
private readonly int _intField;
}
public static int objectToInt(object inputToInt)
{
switch (inputToInt)
{
case int inputInt:
return inputInt;
break;
case string inputString:
if (!int.TryParse(inputString, out int parsedInt))
{
throw new InvalidParameterException($"The input {inputString} could not be parsed to int");
}
return parsedInt;
default:
throw new InvalidParameterException($"Constructor do not support {inputToInt.GetType().Name}");
break;
}
}
Please, please, and pretty please do not try this at home, or work, or anywhere really.
This is a way solve to a very very specific problem, and I hope you will not have that.
I'm posting this since it is technically an answer, and another perspective to look at it.
I repeat, do not use it under any condition. Code is to run with LINQPad.
void Main()
{
(new A(1)).Dump();
(new B(2, -1)).Dump();
var b2 = new B(2, -1);
b2.Increment();
b2.Dump();
}
class A
{
public readonly int I = 0;
public A(int i)
{
I = i;
}
}
class B: A
{
public int J;
public B(int i, int j): base(i)
{
J = j;
}
public B(int i, bool wtf): base(i)
{
}
public void Increment()
{
int i = I + 1;
var t = typeof(B).BaseType;
var ctor = t.GetConstructors().First();
ctor.Invoke(this, new object[] { i });
}
}
Since constructor is a method, you can call it with reflection. Now you either think with portals, or visualize a picture of a can of worms. sorry about this.
In my case, I had a main constructor that used an OracleDataReader as an argument, but I wanted to use different query to create the instance:
I had this code:
public Subscriber(OracleDataReader contractReader)
{
this.contract = Convert.ToString(contractReader["contract"]);
this.customerGroup = Convert.ToString(contractReader["customerGroup"]);
this.subGroup = Convert.ToString(contractReader["customerSubGroup"]);
this.pricingPlan= Convert.ToString(contractReader["pricingPlan"]);
this.items = new Dictionary<string, Member>();
this.status = 0;
}
So I created the following constructor:
public Subscriber(string contract, string customerGroup) : this(getSubReader(contract, customerGroup))
{ }
and this method:
private static OracleDataReader getSubReader(string contract, string customerGroup)
{
cmdSubscriber.Parameters[":contract"].Value = contract + "%";
cmdSubscriber.Parameters[":customerGroup"].Value = customerGroup+ "%";
return cmdSubscriber.ExecuteReader();
}
notes: a statically defined cmdSubscriber is defined elsewhere in the code; My main constructor has been simplified for this illustration.
In case you need to run something before calling another constructor not after.
public class Sample
{
static int preprocess(string theIntAsString)
{
return preprocess(int.Parse(theIntAsString));
}
static int preprocess(int theIntNeedRounding)
{
return theIntNeedRounding/100;
}
public Sample(string theIntAsString)
{
_intField = preprocess(theIntAsString)
}
public Sample(int theIntNeedRounding)
{
_intField = preprocess(theIntNeedRounding)
}
public int IntProperty => _intField;
private readonly int _intField;
}
And ValueTuple can be very helpful if you need to set more than one field.
NOTE: most of the solutions above does not work for structs.
Unfortunately initializing struct fields in a method called by a constructor is not recognized by the compiler and will lead to 2 errors:
in the constructor: Field xxxx must be fully assigned...
in the method, if you have readonly fields: a read-only field cannot be assigned except in a constructor.
These can be really frustrating for example when you just need to do simple check to decide on which constructor to orient your call to.

Inner class (i.e. non-static nested class) in c#

Assume I've defined an interface with multiple properties, e.g.:
interface IFailable<T>
{
T Value { get; }
bool Success { get; }
}
and I want class Foo to expose multiple readonly instances of this, where IFailable properties are calculated from Foo's private non-static data, how would I do that in c#?
In Java its fairly intuitive.
Here's the best I came up in c#, based on https://stackoverflow.com/a/4770231/146567
First create a wrapper:
public class FailableDelegator<T> : IFailable<T>
{
public delegate T valueDelegate();
public delegate bool successDelegate();
private readonly valueDelegate valueHandler;
private readonly successDelegate successHandler;
public T Value { get { return valueHandler(); } }
public bool Success { get { return successHandler(); } }
public FailableDelegator(valueDelegate v, successDelegate s)
{
valueHandler = v;
successHandler = s;
}
}
Then use it to define the properties in Foo's constructor:
public class Foo
{
private double x = 3;
private double y = -9;
public readonly FailableDelegator<double> xPlusY;
public readonly FailableDelegator<double> sqrtY;
public Foo()
{
xPlusY = new FailableDelegator<double>(() => x + y, () => true);
sqrtY = new FailableDelegator<double>(() => Math.Sqrt(y), () => y>=0);
}
}
I had to put the definitions in Foo's constructor because I got error "cannot access non-static field in static context" if I attempted it directly on the field.
I'm not keen on this, because for less trivial examples you end up with a huge amount of code in Foo's constructor.

Constructing class which's property can only be set in constructor, but get anywhere?

I'm trying to create a class which takes value a as a parameters in it's constructor.
It has a private member variable which stores this value. The value should not be changed afterwards.
Here's what I have, it works but I don't think it's the best solution out there:
internal class Foo
{
private int a;
public int A
{
get
{
return this.a;
}
}
public Foo(int a)
{
this.a = a;
}
}
So this way you can not access a from outside of the class, and A-property only has a get method. However, you can still change a from inside the class, and using a property which only returns one variable and nothing else feels stupid.
Am I doing this right, or is there a way to improve my code/more proper way to do this?
Additionally declare your private field readonly and you're there!
public class Foo
{
public Foo(int bar)
{
this.bar = bar;
}
public int Bar
{
get
{
return bar;
}
}
private readonly int bar;
}
“In C# 6 and later, you can initialize auto-implemented properties similarly to fields”. Just like you can initialize a readonly field in a constructor, you can initialize a get-only auto-implemented property in a constructor. Thus, the following now compiles:
public class Class1
{
public int A { get; }
public Class1(int a)
{
A = a;
}
}
…and the following yields an error:
public class Class1
{
public int A { get; }
public Class1(int a)
{
A = a;
}
public void Mutate()
{
// Class1.cs(11,9,11,10): error CS0200: Property or indexer 'Class1.A' cannot be assigned to -- it is read only
A++;
}
}
I like it—you get the terseness of field initialization with the interface/OOP-friendliness of properties.
internal class Foo
{
private readonly int _a;
public int A
{
get
{
return _a;
}
}
public Foo(int a)
{
_a = a;
}
}
This should do it.

Is there a difference between readonly and { get; }

Do these statements mean the same thing?
int x { get; }
readonly int x;
In answer to your question: There is a difference between readonly and {get; }:
In int x { get; } (which won't compile as there's no way to set x - I think you needed public int x { get; private set; } ) your code can keep changing x
In readonly int x;, x is initialised either in a constructor or inline and then can never change.
readonly int x; declares a readonly field on a class. This field can only be assigned in a constructor and it's value can't change for the lifetime of the class.
int x { get; } declares a readonly auto-implemented property and is, in this form, invalid (because you'd have no way whatsoever to set the value). A normal readonly property does not guarantee to return the same value every time it is called. The value can change throughout the lifetime of the class. For example:
public int RandomNumber
{
get { return new Random().Next(100); }
}
This will return a different number everytime you call it. (Yes, this is a terrible abuse of properties).
No, the statements do not mean the same thing. The full version of the property will have a backing variable:
private int _x;
public int X
{
get { return _x; }
}
Another method in the class could modify the backing variable, changing the value of the property:
private void SomeMethod(int someValue)
{
_x = someValue * 5;
}
The readonly keyword only allows a member variable to be assigned in its declaration or in the constructor:
// Both of these compile
private readonly int _x = 1;
public SomeClass()
{
_x = 5;
}
// This will not compile
private void SomeMethod(int someValue)
{
_x = someValue * 5;
}
So a get-only property whose backing variable is marked readonly is a true read-only property.
Other answers are sorta outdated…
In newer versions of C# you can assign a default value to int x { get; } = 33; which changes things.
Basically, it gets compiled down to get-only property with a readonly private backing field. (See https://softwareengineering.stackexchange.com/q/372462/81745 for more details)
Another difference I see is that you can't use the readonly version when using interfaces as you can only define methods and properties.
readonly keyword is making sure that these variables dont change once initialised // it is equalant to making a variable private and setting getter for it.
Example.
public class PlayerAuthData
{
public readonly string emailId, password, userName;
private string hello;
public PlayerAuthData(string emailId, string password, string userName)
{
this.emailId = emailId;
this.password = password;
this.userName = userName;
}
public string Hello
{
get { return hello; }
set { hello = value; }
}
}
public class AuthManager
{
void Start()
{
PlayerAuthData pad = new PlayerAuthData("a#a.com", "123123", "Mr.A");
pad.Hello = "Hi there";
print(pad.Hello);
print(pad.password);
print(pad.emailId);
print(pad.userName);
}
}
Literally, there's no big difference because you've declared x to be private (the default). You can always re-compile your class to make x different.
However, if it were public, the definition public int x { get; } allows you to later expand the definition to something like this:
int x { get {
return DoSomeOperation();
}
}
You can do that without breaking your clients. The implementation of the getter is private and clients call it without knowing if it is a static value or has an operation inside its get accessor.
Propery can have backing variable that can be set using any method of that class
private int a;
public int A{get;}
public void ChangeAMethod(int value){
a=value;
}
However readonly fields can only be assigend in constructor or in-line.

Categories