C#- static variables from class to class - c#

First of all, take a look at my below code:
class A
{
public static int Flag()
{
return 0;// set initial value=0
}
B b= new B();
public void afunc()
{
b.bfunc();
}
}
And class B recieves and sends static variable:
class B
{
A a= new A();
int flag= a.Flag();
public void bfunc()
{
if(flag==0)
{
flag=1;//???? is this wrong???
//do some thing
}
}
}
Class A send to B a static variable with initial value=0; then class A call bfunc from class B. In bfunc() I set flag=1. I'm a new to C#. Can you share me how class A recieves back flag=1 sended by class B. I mean which syntax?

a few things are wrong here
Flag is a method on A, so you cannot change its "value"
Flag is static therefore it does not have an instance which is what I think you want
I suspect you want Flag to be a property of A
public int Flag{get;set;}
You are making new instances of A and B, which may be correct for you but be weary this means you are not referencing existing instances
You have two options
A
this.Flag = b.bFunc();
public int bFunc()
.... return 1;
B
public void bFunc()
... a.Flag = 1;
If you really want static variable then
public static int Flag = 0;
A.Flag = x

Were is no static variable here, you only have a static function int Flag(). To get value of a flag in class A, you must return this value from function bfunc() like this:
public int bfunc()
{
if(flag==0)
{
flag=1;
return flag;
}
}

I don't know if I understood you properly because there are many things wrong with your code. Flag should be a property instead of a method so you can store your value. The way you used it was just tossing out a zero.
First, your two classes. Keep in mind that usually properties should be used as accesssors to private fields, but let's do it the simplest way.
class A
{
public static int Flag = 0;
}
class B
{
public void bfunc()
{
if (A.Flag == 0)
{
A.Flag = 1;
}
}
}
Then use them as follows to change Flag's value.
B bObject = new B();
bObject.bfunc();
// A.Flag is now 1.
Note that bfunc() will change Flag's value to 1 only if it was 0 before.

Related

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.

C# - How can I access the value using properties of classes in an override method?

My Code:
public class A
{
public virtual void displayDetailInfo()
{
}
}
public class B : A
{
public String _a;
public int _n;
public B() { }
public B(String _a, int _n)
{
this._a = _a;
this._n = _n;
}
public String A
{
get { return _a; }
set { this._a = value; }
}
public int N
{
get { return _n; }
set { this._n = value; }
}
public override void displayDetailInfo()
{
Console.WriteLine(A);//To obtain value entered in Main(i.e. f.A)
Console.WriteLine(N);//To obtain value entered in Main(i.e. f.N)
}
}
public class Program
{
public static void Main(String[] args)
{
A v = new A();
A v1 = new B();
B f = new B();
f.A = Console.ReadLine(); //Value to be accessed
f.N = Convert.ToInt32(Console.ReadLine()); //Value to be accessed
v1.displayDetailInfo();
}
}
How can I get the value(f.A and f.N) I entered in Main accessed from the overrided method in class B(i.e. displayDetailInfo()). The code I wrote doesn't obtains any value(i.e. Console.WriteLine(A) gives no value of f.A). So how can I get the value of f.A and f.N from overrided displayDetailInfo()?
Whenever you use new to create a new object, you are creating a new, independent object that has its own state.
Here, you are creating 3 separate objects - v, v1, f.
A v = new Vehicle();
A v1 = new B();
B f = new B();
Changing a property of one of these objects does not affect the properties of the other two objects whatsoever.
Here you change the properties of f, but the properties of v1 is not affected.
f.A = Console.ReadLine();
f.N = Convert.ToInt32(Console.ReadLine());
This is why when you call v1.displayDetailInfo(), it prints null and 0. null and 0 are the default values of string and int respectively. v1's properties have not been set yet, so they hold the default values.
To fix this, just call f.displayDetailInfo() instead.
You can't do this because you v1 is a different instance of B than the one you want to get the values from (f)
Calling f.displayDetailInfo() should give you the result you want
You are setting A of a different object than what you are calling displayDetailInfo on.
I think you meant to do this:
public static void Main(String[] args)
{
A v = new Vehicle();
B v1 = new B();
v1.A = Console.ReadLine(); //Value to be accessed
v1.N = Convert.ToInt32(Console.ReadLine()); //Value to be accessed
v1.displayDetailInfo();
}
It's not possible for v1 to have data you entered in f. The class is just a blueprint, v1 and f are different instances that exist in different parts of the heap.
v1.A is not the same as f.A and v1.N is not the same as f.N
To see the values you entered, you better call:
f.displayDetailInfo()
Also, you're using properties wrong. If you want to use backing fields, the ones with the underscores (_n and _a), you better make them private. And unless you want to have additional logic to the getters or setters you are better off not using backing fields altogether and use auto implemented properties:
public string A { get; set; }
public string N { get; set; }

Passing a static variable by reference in a class constructor

public class Gameplay {
public static int count = 0;
AClass aClass = new AClass(ref count);
}
public class AClass {
public int count { get; set; }
public AClass(ref int c) {
this.count = c;
}
public void printCount() {
Console.WriteLine(this.count.ToString());
}
}
I have two classes like the ones above. Suppose the count variable of Gameplay increases in another class that does Gameplay.count++. I want AClass.count to always be equal to Gameplay.count.
Now, surely I could just use Gameplay.count inside AClass but if I have different counts to pass in different instances of AClass it's better to have the reference to the count you want to access. The above example always writes 0 even if Gameplay count has increased.
What would you expect this code to do?
int c = 0;
int count = c;
c++;
c and count are both references, yet mutating c somehow does not change the value of count.
It's exactly the same situation in your code.
In your code, this line:
this.count = c;
does not copy the reference to c. It copies the value at the time of the assignment to the value-type backing field for count.
You can pass a lambda expression to the constructor if you need AClass to be able to access the value of some arbitrary integer.
public class Gameplay {
public static int count = 0;
AClass aClass = new AClass( () => count );
}
public class AClass {
public int count { get { return this.getCount(); } }
private readonly Func<int> getCount;
public AClass(Func<int> getCount) {
this.getCount = getCount;
}
public void printCount() {
Console.WriteLine(this.count.ToString());
}
}
In your constructor:
public AClass(ref int c) {
this.count = c;
}
... even though the parameter c is passed by reference, as soon as you assign it to this.count, the value gets copied. So any changes to c or Gameplay.count will not be reflected in this.count.
That's going to be challenging, because integers are value types.
You might try using a class that has a Count property, and pass that in instead. If you have multiple objects with Count properties, you could declare an interface with a property of Count (let's call it IHasCount) and have AClass take an instance of IHasCount as its parameter.
Your design begins to sound like it uses the Singleton pattern, which is discouraged nowadays. You might want to read up on that.
Wrap the count into another class
public class CounterHolder
{
public int count = 0;
}
public class Gameplay
{
public static CounterHolder counterHolder = new CounterHolder();
AClass aClass = new AClass(counterHolder);
public void DoSomething()
{
// Something
counterHolder.count++;
aClass.printCount();
}
}
public class AClass
{
private CounterHolder _counterHolder;
public AClass(CounterHolder counterHolder)
{
_counterHolder = counterHolder;
}
public void printCount()
{
Console.WriteLine(_counterHolder.count.ToString());
}
}

Overriding a property

I'm trying to override a property in my program.
Here is basically what I'm trying to do :
class A { public int test = 7; }
class B : A { public int test = 8; }
class Program
{
static void Main(string[] args)
{
A test1 = new A();
A test2 = new B();
Console.WriteLine(test1.test);
Console.WriteLine(test2.test);
}
}
This displays 7 in both case when I'd like it to display 8 in the 2nd case....
I've tried virtual and override as well as new (public new int test = 8;)
But it doesn't seem to work
And yes I know I should use private and getters. I just want to know if it's possible ?
Edit : I'm not a native C# programmer so forgive me if i mix the terms (such as field and propertys)!
I'm trying to override a property in my program.
class A { public int test = 7; }
The problem is that int test is not a property, it is a public field. Fields cannot be overriden.
Here is an example of overriding a property:
class A {
public virtual int test {
get {return 7;}
}
}
class B : A {
public override int test {
get {return 8;}
}
}
Here is a demo of this code on ideone.
test is a field, not a property. You must change it to a property and add the virtual modifier to allow it to be overriden in a subclass. You must then use the override keyword to override the value returned in class B:
class A
{
public virtual int test
{
get { return 7; }
}
}
class B : A
{
public override int test
{
get { return 8; }
}
}
Change this
A test2 = new B();
with this
B test2 = new B();
If you create test2 as A you call A methods

access a static field of a result type of function that has the same name with type

ok this may sound a little crazy but, i have class A and a function, returns an instance of A, also called A() and i have to access a static field of class A.
public class A
{
public static int Num = 1;
}
class Program
{
public A A()
{
Console.WriteLine(A.Num); // Error points here. A.Num.
return new A();
}
}
and i get
'Program.A()' is a 'method', which is
not valid in the given context
what is the solution?
thanks.
Well, you can specify the namespace:
Console.WriteLine(Foo.Bar.A.Num);
If there's no namespace, use the global namespace alias:
Console.WriteLine(global::A.Num);
use the namesapce instead
namesapce test {
public class A
{
public static int Num = 1;
}
class Programs:A
{
public A A()
{
Console.WriteLine(test.A.Num);
return new A();
}
}
}

Categories