I have declared in C# a static public int then that int is suplyed to a thread in it's constructor the thread's job is very simple to increment it but it doesn't happen
Here I declare the static value:
class Global
{
static public int hardcap = 100;
public int speed;
static public Semaphore myhitpoints = new Semaphore(1, 1);
static public Semaphore oponenthitpoints = new Semaphore(1, 1);
static public int mhp = 100;
static public int ohp = 100;
static public int mmana = 0;
static public int omana = 0;
public static Charm dragonblade = new Charm(10, 30, 3, myhitpoints, oponenthitpoints, mhp, ohp, "dragon blade", mmana);
public static Charm dragonshield = new Charm(30, 10, 5, myhitpoints, oponenthitpoints, mhp, ohp, "dragon shield", mmana);
public static Charm b1charm;
public static Charm b2charm;
public static Opponent enemy;
}
class ManaWell
{
int mana_regen;
int cap = 1000;
int target;
public ManaWell(int x, int y)
{
mana_regen = x;
target = y;
}
public void Refill()
{
while (true)
{
// if (this.target + mana_regen <= cap)
if (target+mana_regen<cap)
{
Thread.Sleep(3000);
target += mana_regen;
MessageBox.Show(target.ToString());
}
}
}
}
ManaWell mw1 = new ManaWell(20,Global.mmana);
ManaWell mw2 = new ManaWell(20,Global.omana);
Thread tmw1 = new Thread(new ThreadStart(mw1.Refill));
Thread tmw2 = new Thread(new ThreadStart(mw2.Refill));
tmw1.Start();
tmw2.Start();
So target works fine but y won't increase.
Integer is passed as value and gets locally increased. it will not increase the statical variable which you pass in
Value vs Reference Types
If you want that your external static variable gets updated you could use the ref keyword.
Beside that you should synchronize the access to the variable as you access it from several threads...
if you have "targets" which should be stored and called later you should pass a delegate (which is pointing to the update method) to the constructor. this delegate you can store and call later
When you create your ManaWell object and pass in a variable, it will only be the variable's value that is assigned to target. So when you add to target, you are doing only that; the passed-in variable will not be affected (as you're seeing.)
If you're really passing in a public static int, then to increase it, just do math on it directly (and you don't even have to pass it in):
MyClass.MyStaticInt += aNumber;
The reason is that the value of the variable is passed to the constructor. You are only incrementing the variable local to your class.
Related
I'm new to c# (& coding in general) and i can't find anything pointer equivalent.
When i searched google i got something like safe/unsafe but that's not what i needed.
Like in c++ if you had a pointer and it pointed towards some value, the change in the pointer would cause change in the original variable.
Is there anything of such in c#?
example-
static class universal
{
public static int a = 10;
}
class class_a
{
public void change1()
{
universal.a--;
}
}
class class_b
{
public void change2()
{
some_keyword temp = universal.a; //change in temp gives change in a
temp-= 5; //the purpose of temp is to NOT have to write universal.a each time
}
}
...
static void Main(string[] args)
{
class_b B = new class_b();
class_a A = new class_a();
A.change1();
Console.WriteLine(universal.a);//it will print 9
B.change2();
Console.WriteLine(universal.a);//it will print 4
Console.ReadKey();
}
Edit-
thank you #Sweeper i got the answer
i had to use ref int temp = ref universal.a;
If you don't want unsafe code, I can think of two options.
Wrapper object
You can create a class like this, that wraps an int:
public class IntWrapper {
public int Value { get; set; }
}
Then change a's type to be this class:
static class Universal
{
public static IntWrapper a = new IntWrapper { Value = 10 };
}
class class_a
{
public void change1()
{
universal.a.Value--;
}
}
class class_b
{
public void change2()
{
Universal temp = universal.a; //change in temp gives change in a
temp.Value -= 5;
}
}
This works because classes are reference types, and a holds a reference (similar to a pointer) to a IntWrapper object. = copies the reference to temp, without creating a new object. Both temp and a refers to the same object.
ref locals
This is a simpler way, but it is only for local variables. You can't use this for a field for example.
public void change2()
{
ref int temp = ref universal.a; //change in temp gives change in a
temp -= 5;
}
C# has references which are very similar to pointers. If a and b are both references to the same object, a change in a will also be seen in b.
For example, in:
class X {
public int val;
}
void Main()
{
var a = new X();
var b = a;
a.val = 6;
Console.WriteLine(b.val);
}
6 will be written.
If you change the declaration of X from class to struct, then a and b will no longer be references, and 0 will be written.
In c# Pass By Reference is used instead of pointers, Here's the corrected code
static class universal
{
public static int a = 10;
}
class class_a
{
public void change1()
{
universal.a--;
}
}
class class_b
{
public void change2(ref int val)//use ref keyword for reference
{
int temp = val; //change in temp gives change in a
val -= 5;
}
}
static void Main(string[] args)
{
class_b B = new class_b();
class_a A = new class_a();
A.change1();
Console.WriteLine(universal.a);//it will print 9
B.change2(ref universal.a); //pass value by reference using ref keyword
Console.WriteLine(universal.a);//it will print 4
Console.ReadKey();
}
In some cases (when an optimization is very needed) you can use almost C-like pointers. You can only do that by explicitly specifying you are aware of the risk by placing your code in unsafe scope:
unsafe
{
int number = 777;
int* ptr = &number;
Console.WriteLine($"Data that pointer points to is: {number} ");
Console.WriteLine($"Address that pointer holds: {(int)ptr}");
}
The unsafe context allows you to use pointers directly. Please note that by default this option is turned off from your project. To test this you would need to right-click on project>Properties>Build - Allow unsafe code
Like this?
using System;
namespace Demo
{
class Program
{
static void Main()
{
var test = new class_a();
test.change1();
Console.WriteLine(universal.a); // Prints 18
}
}
static class universal
{
public static int a = 10;
}
class class_a
{
public void change1()
{
ref int x = ref universal.a;
++x;
++x;
++x;
x += 5;
}
}
}
[EDIT: I noticed that this is the same as the last part of Sweeper's answer, but I'll leave this here since it focusses just on that solution.]
namespace Practice
{
public class LargestPrimeFactor {
public static void main(String[] args) {
readonly long NUM = 600851475143L;
int i;
int n;
int flag = 0;
long primeFactor = 1;
long factor = 1;
for(i=2; i<NUM/2; i++) {
flag = 0;
for(n=2; n < i/2; n++) {
if(i % n == 0) {
flag = 1;
}
}
if(flag == 0){
factor = i;
if(NUM % factor == 0) {
primeFactor = factor;
Console.WriteLine("factor = " + factor);
}
}
}
Console.WriteLine(primeFactor);
}
}
}
Please explain what I’m doing wrong. I don’t know how to declare this variable so that it is read-only. When I put it outside of the method, I get different errors.
The readonly modifier is valid at the class level, so you could refactor it as:
public class LargestPrimeFactor {
readonly long NUM = 600851475143L;
public static void main(String[] args) {
// ...
}
}
Alternatively, you can use the const keyword either at the field level or inside a method:
public class LargestPrimeFactor {
const long NUM = 600851475143L;
public static void main(String[] args) {
// ...
}
}
or
public class LargestPrimeFactor {
public static void main(String[] args) {
const long NUM = 600851475143L;
// ...
}
}
readonly is most useful for variables that will be fully initialized before the constructor completes but don't have a constant representation, e.g.
readonly DateTime startedAt = DateTime.Now;
You want to declare NUM as a const instead of a readonly.
If you read the documentation for readonly, you'll see that it doesn't apply to variables declared inside a method. The keyword can only be applied to:
readonly field declarations
readonly struct definitions
readonly instance members
ref readonly method return
If you want a variable that's defined inside a method to not be modified, you can declare it with the const keyword:
public static void Main(string[] args)
{
const long num = 600851475143L;
}
I wanted to do something similar, but for a value that was calculated at runtime. Instead of const long NUM = 600851475143L I used the new(ish) local function feature - not exactly const or readonly, but a way to lock down a value
long NUM() => someLongRuntimeValue;
. . .
for(i=2; i<NUM()/2; i++) {
. . .
This costs of a couple parentheses and a bit of runtime overhead - in my case the value was going to be used only a few times. It was a defensive code practice in a module edited by many people, a way of saying "I know you might think you want to change this value, but if you do you will break things" - my future self being one of the people I'm talking to.
I have this tiny static class. I need to initialize this jagged array and i'll have to do some more stuff later.
namespace Kerumaton
{
static internal class WorldGrid
{
static public int gridWidth;
static public int gridHeight;
static public int gridSizeX, gridSizeY;
static public int[][] gridArray;
static WorldGrid()
{
gridWidth = 10;
gridHeight = 10;
gridSizeX = World.imageWidth % gridWidth;
gridSizeY = World.imageHeight % gridHeight;
gridArray = new int[gridSizeX][];
for (int i = 0; i < gridArray.Length; i++)
{
gridArray[i] = new int[gridSizeY];
}
}
}
}
But i get a warning telling me that it would be a good idea to remove the static constructor and initialize the variable where they are declared.
Sure, yes please, i hear this have significant performance impact.
But how ? Is there a way to run code when declaring a variable ? Am i misunderstanding something ? is the warning a false alarm ? I'm sure the answer is obvious but my google-fu only show me very simple exemple like dictionary inline initialization.
I'm using C# 8, Core 3.x, VS2019
It turn out there is a simple way to remove the warning. I assumed the warning existed simply because of the presence of the static constructor, but it is not the case.
While it doesn't strictly answer my question of "how to run code at initialization" it fix the warning :
namespace Kerumaton
{
static internal class WorldGrid
{
static public int gridWidth = 10;
static public int gridHeight = 10;
static public int gridSizeX = World.imageWidth % gridWidth;
static public int gridSizeY = World.imageHeight % gridHeight;
static public int[][] gridArray = new int[gridSizeX][];
static WorldGrid()
{
for (int i = 0; i < gridArray.Length; i++)
{
gridArray[i] = new int[gridSizeY];
}
}
}
}
I have two classes, one for defining the algorithm parameters and another to implement the algorithm:
Class 1 (algorithm parameters):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VM_Placement
{
public static class AlgorithmParameters
{
public static int pop_size = 100;
public static double crossover_rate = 0.7;
public static double mutation_rate = 0.001;
public static int chromo_length = 300;
public static int gene_length = 4;
public static int max_allowable_generations = 400;
static Random rand = new Random();
public static double random_num = rand.NextDouble();
}
}
Class 2 (implement algorithm):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VM_Placement
{
public class Program
{
public struct chromo_typ
{
public string bits;
public float fitness;
//public chromo_typ(){
// bits = "";
// fitness = 0.0f;
//}
chromo_typ(string bts, float ftns)
{
bits = bts;
fitness = ftns;
}
};
public static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng =
new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
public string GetRandomBits()
{
string bits="";
for (int i = 0; i < VM_Placement.AlgorithmParameters.chromo_length; i++)
{
if (VM_Placement.AlgorithmParameters.random_num > 0.5f)
bits += "1";
else
bits += "0";
}
return bits;
}
public static void Main(string[] args)
{
Random rnd = new Random(GetRandomSeed());
while (true)
{
chromo_typ[] Population = new chromo_typ[VM_Placement.AlgorithmParameters.pop_size];
double Target;
Console.WriteLine("\n Input a target number");
Target = Convert.ToDouble(Console.ReadLine());
for (int i = 0; i < VM_Placement.AlgorithmParameters.pop_size; i++)
{
Population[i].bits = GetRandomBits();
Population[i].fitness = 0.0f;
}
}
}
}
}
I am getting an error on Population[i].bits = GetRandomBits(); in Main().
Error is:
An object reference is required for the non-static field, method, or property 'VM_Placement.Program.GetRandomBits()'
Am I missing anything?
The Main method is Static. You can not invoke a non-static method from a static method.
GetRandomBits()
is not a static method. Either you have to create an instance of Program
Program p = new Program();
p.GetRandomBits();
or make
GetRandomBits() static.
It looks like you want:
public static string GetRandomBits()
Without static, you would need an object before you can call the GetRandomBits() method. However, since the implementation of GetRandomBits() does not depend on the state of any Program object, it's best to declare it static.
The Main method is static inside the Program class. You can't call an instance method from inside a static method, which is why you're getting the error.
To fix it you just need to make your GetRandomBits() method static as well.
i'm new at C # and i'm creating a racetrack simulator, but i'm currently encountering some issues when i run my code. I have an array of four Greyhound objects, and if I call Greyhound.Run on my form1.cs and i don't have a "MessageBox.Show("Distance" + distance)" on my Run method, which shows me how many pixels each greyhound is supposed to move, all of the greyhounds end up moving the same distance. I don't understand why this is happening
namespace Race
{
class Greyhound
{
public int StartingPosition;
public int RacetrackLength;
public PictureBox MyPictureBox = null;
public int Location = 0;
public Random Randomizer;
public bool Run()
{
Point p = MyPictureBox.Location;
if (p.X + MyPictureBox.Width >= RacetrackLength)
{
//TakeStartingPostion();
return true;
}
else
{
Randomizer = new Random();
int distance = Randomizer.Next(100);
MessageBox.Show("Distance is " + distance);
p.X += distance;
MyPictureBox.Location = p;
return false;
}
}
public void TakeStartingPostion()
{
Point P = MyPictureBox.Location;
P.X = StartingPosition;
MyPictureBox.Location = P;
}
}
}
namespace Race
{
public partial class Form1 : Form
{
Guy[] guys = new Guy[3];
Greyhound[] hounds = new Greyhound[4];
public Form1()
{
InitializeComponent();
hounds[0] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound1,
RacetrackLength = 636
};
hounds[1] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound2,
RacetrackLength = 636
};
hounds[2] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound3,
RacetrackLength = 636
};
hounds[3] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound4,
RacetrackLength = 636
};
}
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < hounds.Length; i++)
{
hounds[i].Run();
}
}
}
}
It's because you're calling new Random() each time the Run() method hits the else block. The default Random constructor initializes the pseudorandom number generator based on the current time. When there's no interruption, all 4 method run at "the same time", so they spit out the same random numbers. To fix this, either create only a single Random, or else use a different seed for each one (by using the Random constructor that takes a seed as a parameter.)
Something like this would work:
public class Greyhound
{
public static Random randomizer = new Random();
// ... In the run method ...
int distance = Greyhound.randomizer.Next(100);
}
Update: As Groo points out, if you were actually calling Next() from multiple threads, the code I've shown isn't thread-safe. While that's not the case with your code, it's a good idea to be aware of issues like this earlier rather than later. The general solution to this (potential) problem is to surround the call to Next() with a lock, like so:
// ... After the declaration of randomizer ...
private static object randomLock = new object();
// ... New Next() call...
lock (randomLock)
Greyhound.randomizer.Next(100);
Since you probably call the Run methods of all of your objects quickly in succession, each instance of the Random class gets instantiated with the same seed, returning the same pseudo-random number.
You can solve this problem by creating a static random class which will have a single (Singleton) Random instance, making sure that each of your callers gets the next number in succession.
With some locking for thread safety, it would look something like:
public class StaticRandom
{
private static readonly Random _r = new Random();
private static object _lock = new object();
public static int Next(int max)
{
lock (_lock)
return _r.Next(max);
}
}
And then use it without instantiating it:
// no need for the "Randomizer" field anymore
int distance = StaticRandom.Next(100);
Jon Skeet has the full implementation in his miscutil library, along with some usage info.