how to protect static int in C# - c#

I am learning C# so I am still on the basics here. This is my code
class foo
{
protected int id;
protected string data;
static int nextId = 1;
public int Id
{
get { return id; }
}
public foo()
{
this.id = nextId++;
}
public foo(string somedata)
{
this.data = somedata;
this.id = nextId++;
}
}
This code works just fine for now. All objects will have a unique ID with them.
Problem is: I don't want the first ID to be 1, I want it to be the number on the first line of the file given as an argument to the application from the commandline. If no file is specified or the file does not exist, then it can be one. Is there a way to make a one-time method to set nextId so it cannot be tampered with outside of the class after it has been once set?
Duh... I guess this is the trick. Still, I'd like to know if there is some build in way to make variables that can only be set once.
public int nextId
{
set {if(nextId<1) nextId = value;}
}

You can implement static constructor, which assigns proper value to nextId before first usage of foo class:
using System.IO;
using System.Linq;
...
class foo
{
...
static int nextId;
// read-only property which however can be assigned in the constructor
public int Id {get;}
// This static costructor will be called once before 1st usage of foo class
static foo() {
//TODO: put the right file name here
string fileName = Environment.GetCommandLineArgs()[1];
nextId = int.Parse(File
.ReadLines(fileName)
.First());
}
public foo()
{
//Let's increment nextId in thread-safe manner
Id = Interlocked.Increment(ref nextId);
}
...
}

You can do this
class foo
{
private static int nextId = 1;
private static bool isNextIdSet;
public SetId(newId)
{
if (!isNextIdSet) nextId = newId;
isNextIdSet = true;
}
}
So the nextId can be set only once from outside the class.
UPDATE: if you prefer to use this with many variables, you can create a helper for this, such as
class SetOnlyOnce<T>
{
private bool isSet;
public T Value
{
get;
set
{
if (!isSet) Value = value;
isSet = true;
}
}
}
Then use it as
class Foo
{
public SetOnlyOnce<int> prop1 {get;set;}
public SetOnlyOnce<string> prop2 {get;set;}
}
class Bar
{
public Bar()
{
var foo = new Foo();
foo.prop1.Value = 2;
foo.prop1.Value = 3; // this doesn't set.
}
}

As an alternative to Dmitry's answer, you can define the initialization through a static method. I prefer avoiding static constructors unless multiple fields need to be initialized simultaneously.
using System.IO;
using System.Linq;
...
class foo
{
...
// The initialization will be called at some time before first use of nextId.
private static int nextId = GenerateInitialNextId();
// read-only property which however can be assigned in the constructor
public int Id {get;}
private static int GenerateInitialNextId() {
//TODO: put the right file name here
string fileName = Environment.GetCommandLineArgs()[1];
return int.Parse(File
.ReadLines(fileName)
.First());
}
public foo()
{
//Let's increment nextId is thread-safe manner
Id = Interlocked.Increment(ref nextId);
}
...
}

Related

c# initialize static variable from different classes

What I have is:
public static class IDs {
public static string someID { get; set; }
static IDs() {
log.info(someID);
// use someID here
}
}
public class otherClass {
public void otherMethod(string sym) {
IDs.someID = sym;
}
}
and then using an instance of otherClass like this:
otherClassInstance.otherMethod("someStringSymbol");
I dont have any build errors, but log.info(someID); is printing null.
I was expecting it to be someStringSymbol.
This is because the static constructor is called automatically before the first instance is created or any static members are referenced..
This means that when an instance of otherClass invokes IDs.someID = sym; the first operation that gets executed is the static constructor, i.e. the code inside static IDs().
At this point the static variable has not yet been initialized, and you are basically executing log.info(null);.
After the static constructor completes, the variable is initialized, so you should be able to see its value inside otherMethod, after the first reference of IDs.
Given the OP's requirement:
I want to use the value passed in someID in a switch statement
The solution could be to simply execute a static method whenever a new value is set, with the help of explicit getters and setters:
public static class IDs
{
private static string _someID; // backing field
public static string SomeID
{
get { return _someID; }
set
{
_someID = value;
DoSomethingWithSomeID();
}
}
private static DoSomethingWithSomeID()
{
// Use SomeID here.
switch (IDs.SomeID)
{
...
}
}
}
public class OtherClass
{
public void OtherMethod(string sym)
{
// This will set a new value to the property
// and invoke DoSomethingWithSomeID.
IDs.SomeID = sym;
}
}
DoSomethingWithSomeID will be invoked every time someone sets a new value to SomeID.
I dont think what you are trying to do is suited to static classes. I would try the following
public class IDs{
public string someID{ get; set; }
public IDs(string someId){
this.someID = someId;
log.info(this.someID);
//use someID here
}
}
pulic class otherClass{
public otherMethod(string sym){
IDs id = new IDs(sym);
}
}
public class anotherClass{
//access instance of otherClass in wrp and call otherMethod()
wrp.otherMethod("someStringSymbol")
}

How to acess variable value from one class to another class?

I want to access a string from one class to another. I have used the property method as follows -
Myclass.cs
public class MyClass
{
private string _user;
public string user
{ get { return this._user; } set { this._user = value; } }
}
consumption.aspx.cs
I am assigning the value to user in a function
MyClass m = new MyClass();
m.user = "abc"
Now when I try to use this value in my another function which is called after this value is assigned
RawDal.cs
MyClass m = new MyClass();
string x = m.user;
I get empty value... How to do it?
As already mentioned in the comments you are creating two separate instances of MyClass which results simplified in something like:
int a;
a = 3;
int b;
Console.WriteLine("a: " + b); //<-- here it should be obvious why b is not 3
You can work around this in 3 ways:
1) Use the same instance of MyClass for the second call, but in this case you need to be in the same scope or pass the instance on to the new scope.
2) Make the property/member static:
public class MyClass
{
public static string User { get; set; } //the "static" is the important keyword, I just used the alternative property declaration to keep it shorter
}
Then you can access the same User value everywhere via MyClass.User.
3) Use a singleton:
public class MyClass
{
private static MyClass instance = null;
public static MyClass Instance
{
get
{
if(instance == null)
instance = new MyClass();
return instance;
}
}
public string User { get; set; }
}
Then you can access it via MyClass.Instance.User.
There are possibly some more solutions, but these are the common ones.
You are not using the same instance. Try
public class MyClass
{
private string _user;
public string user
{ get { return this._user; } set { this._user = value; } }
}
public string YourFunction()
{
MyClass m = new MyClass();
m.user = "abc"
return m.user;
}
If all you want to return is a string try something like
string x = YourFunction();

Incrementing a unique ID number in the constructor

I'm working on an object in C# where I need each instance of the object to have a unique id. My solution to this was simply to place a member variable I call idCount in the class and within the constructor I would have:
objectID = idCount;
idCount++;
I thought that this would solve my problem but it seems that idCount never gets incremented even though the constructor gets called multiple times. For example if idCount = 1, the objectID for all the objects are still 1. Why doesn't idCount++ work?
Any help would be appreciated. Apologies if my explanation isn't adequate, I'm not sure how else to explain it.
You need a static property in your class, BUT, you need to assign it to an instance variable within the class if you want each object to contain the id it was created with.
Also, you'll want to use Interlocked.Increment on the counter in case you are updating multiple instances simultaneously:
public class Foo
{
private static int m_Counter = 0;
public int Id { get; set; }
public Foo()
{
this.Id = System.Threading.Interlocked.Increment(ref m_Counter);
}
}
You could use a static variable in your class that gets updated when the object is initialized.
public class Foo
{
private static int ID = 0;
private int myId = 0;
public int MyId
{
get { return myId; }
}
public Foo()
{
ID++;
this.myId = ID;
}
}
As everyone has pointed out, static variables are the specific answer to your question. But static variables only have scope within the process in which they were created and there is no relationship across processes (for example, a load balanced web environment).
If what you are looking for is a unique way to identify an object instance for the duration of its lifetime, I suggest something like:
byte[] bytes = new byte[8];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto .GetBytes( bytes );
long id = BitConverter.ToInt64( bytes, 0 );
This will give you a random number which has an extremely low (roughly 0-1 in 100,000,000) chance of collision and you don't need to worry about keeping track of it.
You set IdCount is static member of MyObject.
public class MyObject
{
static int idCount = 0;
private int _objectID;
public int ObjectID
{
get { return _objectID; }
}
public MyObject()
{
idCount++;
_objectID = idCount;
}
}
public sealed class SingletonIdGenerator
{
private static long _id;
private SingletonIdGenerator()
{
}
public string Id
{
get { return _id++.ToString().Substring(8); }
}
public static SingletonIdGenerator Instance { get { return Nested.instance; } }
private class Nested
{
static Nested()
{
_id = DateTime.Now.Ticks;
}
internal static readonly SingletonIdGenerator instance = new SingletonIdGenerator();
}
}

How to implement instance numbering?

I don't know if the title is clear but basically I am trying to implement something like this:
public class Effect
{
public int InternalId ...
public void ResetName() ...
}
When ResetName is called, this will reset the name of the object to:
"Effect " + someIndex;
So if I have 5 instances of Effect, they will be renamed to:
"Effect 1"
"Effect 2"
"Effect 3"
...
So I have another method (ResetNames) in another manager/container type that calls ResetName for each instance. And right now I have to pass an integer to ResetName while keeping a counter myself inside ResetNames. But this feels not as clean and this prevents me from calling ResetName myself outside the manager class, which is valid.
How to do this better/cleaner?
As for the InternalId, it's just some id that stores the creation order for everything. So I can't just rely on these, because the numbers are large, like 32000, etc.
EDIT: Container ResetNames code:
int count = 1;
var effects = this.Effects.OrderBy ( n => n.InternalId );
foreach ( Effect effect in effects )
{
effect.ResetName ( count );
++count;
}
Have a manager class that handles the naming. It will also handle creation of the child class, and will embed a reference to itself. You can now call ResetName() on the child class, and it will have it's manager handle whatever logic needs to be done.
I'm not sure exactly what you want the results to be in various situations, but hopefully the following will be of some help:
public class Effect {
{
private EffectManager _manager;
public string Name {get;set;}
public Effect(EffectManager manager) {
_manager = manager;
}
public void ResetName() {
Name = _manager.GetNextName();
}
}
public class EffectManager {
private List<Effect> Effects;
private int currentIndex;
public Effect CreateEffect() {
var e = new Effect(this);
Effects.Add(e);
}
public string GetNextName() {
return "Effect " + currentIndex++;
}
public void ResetAllNames() {
currentIndex = 0;
foreach(var effect in Effects) {
effect.Name = GetNextName();
}
}
}
One of many possibilities: give your Effect class a public property Name, and in the method where you populate a list or array of Effect objects, assign the name. You can also give the Effect class an integer property and set the number, so that you can sort them, if you want.
public class Effect()
{
public string Name() { get; set; }
}
public class SomeClass()
{
private List<Effect> Effects;
public static void WhateverMethod()
{
for (var i = 0; i < Effects.Count; i++)
Effects[i].Name = "Effect " + (i + 1).ToString();
}
}
Are the names specific to all instance or to all instances in a given collection?
If the former you could do something like:
public class Effect
{
private static int _lastId;
public Effect()
{
InternalId = _lastId++;
}
public string Name
{
get { return "Effect" + InternalId.ToString(); }
}
public int InternalId ...
}
Namespace Diagnostics
<Conditional("DEBUG")> _
Public NotInheritable Class UniqueID
Private Shared _idBase As Integer
Private Sub New()
'keep compiler from creating default constructor
End Sub
Public Shared Function GetNext() As String
Return "ID" + System.Threading.Interlocked.Increment(_idBase).ToString("00")
End Function
End Class
End Namespace
Instead of having Name be a stored property, could you do something like this?
public class Effect
{
public int InternalId ...
public int Index;
public string BaseName;
public string Name
{
get
{
return BaseName + index;
}
}
}

Call one constructor from another

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.

Categories

Resources