Which is better to achieve efficiency if i need to use this object in many methods in my class?
Doing this:
Create object above of class so i can accecc c in multiple methods.
using System;
class Program
{
static Customers c = new Customers("text1", "text2");
public static void Main()
{
}
}
Or doing this:
Create object inside methods so every time i need to use c object i
must create it.
using System;
class Program
{
public static void Main()
{
Customers c = new Customers("text1", "text2");
}
}
Generally it is a best practice to restrict variables' scope(s) as much as possible (great explaination why). This means that if you need a variable to be accessible by multiple methods, then great, make a global variable. If not, then make it local because that's all it needs to be. Neither of these are "more efficient" than the other per-say, they are just used in different scenarios.
For example, let's say you're writing a simple calculator-like program to add/subtract 2
random numbers.
static int num1;
static int num2;
static void Main(string[] args){
var rand = new Random();
num1 = rand.Next(10); // Generate random number between 0 and 10
num2 = rand.Next(10);
Add();
Subtract();
Console.ReadLine();
}
static void Add(){
Console.WriteLine($"{num1} + {num2} = {num1+num2}");
}
static void Subtract(){
Console.WriteLine($"{num1} - {num2} = {num1-num2}");
}
In this example, num1 and num2 need to be processed by the Add() and Subtract() methods, so we make them global variables. The rand variable on the other hand is only needed in the Main() method, so we keep it local.
Global variables can also be accessed from within other classes (depending on their scope), whereas local variables cannot.
Related
Which is better and is there a difference in the random results ?
void Func1(Random rand)
{
var num=rand.Next();
}
void Func2(ref Random rand)
{
var num=rand.Next();
}
They are functionally equivalent. You don't update the rand reference in the function so passing it by ref does nothing.
Rule of thumb: don't use ref unless you absolutely have to and understand what it does.
1) Never use ref if you don't need it explicitely.
2) Usually you shouldn't need to pass Random through methods. If you have to, probably you are doing something wrong in your code.
Why? Because to be sure of a true randomness, it's better to always use the same Random instance instead of creating many of them.
That's why you should always declare one and use it around, like in this example:
class Program
{
static void Main(string[] args)
{
RandomNumbersPrinter randomNumbersPrinter = new RandomNumbersPrinter();
int randomInteger = randomNumbersPrinter.GetRandomInteger();
Console.WriteLine(randomInteger);
}
}
public class RandomNumbersPrinter
{
private static readonly Random _random = new Random();
public int GetRandomInteger()
{
return _random.Next();
}
}
Since Random is a reference type, the only difference is that the reference to the instance get copied when calling Func1.
In Func2, you are passing the actual existing reference to the Random itself to the method.
Please consult the docs for more information about this.
The bottom line is that you shouldn't use the ref keyword here unless you intend to assign rand to a new Random object in the method.
So I am trying to learn some C#, currently on a short course on An Introduction to Programming. I have a question in my text book which is giving me pretty much simular results to this post Same random numbers from instantiated class
I have tried to follow the solution but get the same results every time, the task is to Roll two dice and display their numbers using 2 instances of a class. But like the post above the "dice" role the same number. If I call the same instance of the class twice and out put the values to separate labels I get completely different values like i want. here is the class:
namespace CH10_Ex10._5
{
public class ThrowDice
{
public ThrowDice()
{
}
private Random newRandom = new Random();
private int x;
public void Throw()
{
x = newRandom.Next(1, 7);
}
public int value
{
get
{
return x;
}
}
}
}
and here is my main form:
namespace CH10_Ex10._5
{
public partial class Form1 : Form
{
ThrowDice Die1;
ThrowDice Die2;
public Form1()
{
InitializeComponent();
Die1 = new ThrowDice();
Die2 = new ThrowDice();
}
private void button1_Click(object sender, EventArgs e)
{
Die1.Throw();
dieOneLabel.Text = Convert.ToString(Die1.value);
Die2.Throw();
dieTwoLabel.Text = Convert.ToString(Die2.value);
}
}
}
I have tried to find an answer with out opening a new post so i am sorry if this have been answered before. I am very green at this.
My understanding is that if i declare objects with new, then i am creating separate instances of the class and therefore when i call those objects they should run independently/separately, but use the same rules which are specified in my class. I have tried to debug and as i step through the code i see the 2 separate calls to the class and what it looks like is the call 1 generates a random number eg 6 and call 2 seems to generate 6 as well.
thanks in advance
The problem is that the random instance will be initialized with the current time since you're using the default constructor. Since that happens on two instances very quick they get the same seed here:
public Form1()
{
InitializeComponent();
Die1 = new ThrowDice();
Die2 = new ThrowDice();
}
You could make it static:
private static Random newRandom = new Random();
Random constructor:
The default seed value is derived from the system clock and has finite
resolution. As a result, different Random objects that are created in
close succession by a call to the default constructor will have
identical default seed values and, therefore, will produce identical
sets of random numbers.
However, Random is not thread safe. So you should have a look at this answer.
This is also really worth reading: C# in Depth: Random numbers which suggests to use ThreadLocal<T> which is new in .NET 4 instead of static with lock.
You can fix this using same random instance in both instances.For example you can add a constructor like this:
private Random newRandom;
public ThrowDice(Random rnd)
{
newRandom = rnd;
x = newRandom.Next(1, 7);
}
Then:
Random rnd = new Random;
public Form1()
{
InitializeComponent();
Die1 = new ThrowDice(rnd);
Die2 = new ThrowDice(rnd);
}
What i usually use :
private Random newRandom = new Random(Guid.NewGuid().GetHashCode());
it's the first question I ask so please be tolerant if I do something wrong.
I am writing a software to read data from a serial port a then use it to update the status of a static list of objects. Every data I receive is a communication of a wireless node and it represents its status. I solved the reading part and I am handling the search and update part.
I would like to use the background worker to search the element in the list and then update it, assuring the user a clean and smooth UI. The problem is that I read the bytes through a static function, and from that static function I should call the backgroundworker to perform the task. I read on the dotnetperls guide that "RunWorkerAsync can be called anywhere in your code.", but when I try to call it from the static function, Visual Studio doesn't let me do it.
Can anyone help me?
[edit: code added]
This is the extract of my static method:
public static void Add(Byte[] received)
{
List<byte[]> messages = new List<byte[]>();
int lastdollars = 0;
byte[] tempmess = new byte[20]; //The message is 20 digits
lock (BufferLock)
{
//I add the last bytes to the buffer (it's a list of bytes)
Buffer.AddRange(received);
if (Buffer.Count < TOTALMESSAGELENGTH) return;
String temp = Encoding.UTF8.GetString(Buffer.ToArray());
//I check the buffer to look for complete messages (there are tokens at the start and at the end
for (int i = 0; i <= (temp.Length - TOTALMESSAGELENGTH + 1); i++)
{
if ((temp.Length > i + TOTALMESSAGELENGTH) &&
(temp.Substring(i, TOKENLENGTH) == STARTTOKEN) &&
(temp.Substring((i + TOKENLENGTH + MESSAGELENGTH), TOKENLENGTH) == ENDTOKEN))
{
//if I find a message, I put it into the list of messages, I save its position and I continue to look for other messages
tempmess = Encoding.UTF8.GetBytes(temp.Substring(i, TOTALMESSAGELENGTH));
messages.Add(tempmess);
lastdollars = i;
i += TOTALMESSAGELENGTH - 1;
}
}
if (messages.Count == 0)
return;
//I delete the buffer that I'm using and I need to call the background worker
Buffer.RemoveRange(0, (lastdollars + TOTALMESSAGELENGTH));
}
worker.RunWorkerAsync(messages); //Error: An object is required for the non-static field, method, or property 'namespace.Form1.worker'
}
I tried both to define manually the backgroundworker with:
private readonly BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
and adding it through the Toolbox, but the result is the same.
You cannot access instance variables in static methods. Hence the error. Try and make the BackgroundWorker instance static. Something like the following.
private readonly static BackgroundWorker worker = new BackgroundWorker();
Not very sure if this will not break any other of your code.
Hope this helps.
This doesn't really have anything to do with BackgroundWorker or any specific class. It is just how the C# language works.
You can't access non-static members from a static function. A static function has no implicit this parameter that makes it run against a particular instance of the class. You can run it without ever creating any instances of the class.
This worker
private readonly BackgroundWorker worker = new BackgroundWorker();
will be created once for each instance of the class. But you can call the Add function without having any instances.
For example, this doesn't work for the same reason:
class Adder
{
public int sum = 0;
public static void Add(int x)
{
sum += x; // can't reference "sum" from static method!
}
}
...
Adder.Add(5)
but this works:
class Adder
{
public int sum = 0;
public void Add(int x) // no longer static
{
sum += x; // this refers to the "sum" variable of this particular instance of Adder
}
}
...
var adder = new Adder();
adder.Add(5);
and this also works (but differently!):
class Adder
{
public static int sum = 0; // we made sum static (there is exactly one, instead of a separate sum for each instance)
public static void Add(int x)
{
sum += x; // this refers to the static sum variable
}
}
...
Adder.Add(5);
I want the "BombenGenerieren(anzahlMinen)" only one time, how should I write it, that it doesn't generates new bombs every round?
public Game(int anzahlMinen, int xeingabe, int yeingabe)
{
_minenArray = new int[5, 5];
_emptyArray = new int[5, 5];
_boolArray = new bool[5, 5];
program = new Program();
zeichnen = new Draw();
BombenGenerieren(anzahlMinen);
FillPlayMap();
Umdreher(yeingabe, xeingabe);
zeichnen.OpenField(_minenArray, _boolArray);
//SeenMap();
}
I'm assuming Game is a constructor and you want to execute BombenGenerieren once and share it between instances.
What you should do, is make BombenGenerieren static and store whatever the effect of BombenGenerieren is in one or more static fields or properties. You should then call Game.BombenGenerieren before instantiating new Game objects, or alternatively create a static constructor as follows:
public static Game()
{
BombenGenerieren(anzahlMinen);
}
The static constructor will be executed the first time you use the Game type. Note that it does no take parameters, so anzahlMinen will have to be a constant. If that is a problem, go with the regular static method.
Another alternative is to encapsulate the result of the BombenGenerieren method in an object and pass that to the Game constructor, whcih can apply the result to each new class.
Basically, utilize a boolean variable to keep track of the execution of BombenGenerieren.
boolean bombenGeneriert = false;
public Game(int anzahlMinen, int xeingabe, int yeingabe) {
//...
BombenGenerieren(anzahlMinen);
//...
}
public void BombenGenerieren(int minen) {
if (!bombenGeneriert) {
bombenGeneriert = true;
//the rest of your code in this method
}
}
This will set bombenGeneriert to true the first the method is executed. Now on every execution it checks for !bombenGeneriert which will evaluate to false.
Besides, you should consider rearranging your code. I suspect you call Game() more than once, so you should probably relocate your BombenGenerieren() method, somewhere outside Game().
If Game is your class and Game() a constructor, than bombenGeneriert hast to be static:
static boolean bombenGeneriert = false;
I'm very new to C# but am learning more and more every day. Today, I'm trying to build a simple console calculator and need help passing a variable from the function to Main() so I can use it in an if-else to determine what function should execute.
public static void Main(string[] args)
{
int decision = Introduction();
Console.Clear();
Console.WriteLine(decision);
Console.ReadLine();
}
public static int Introduction()
{
int decision = 0;
while (decision < 1 || decision > 7)
{
Console.Clear();
Console.WriteLine("Advanced Math Calculations 1.0");
Console.WriteLine("==========================");
Console.WriteLine("What function would you like to perform?");
Console.WriteLine("Press 1 for Addition ++++");
Console.WriteLine("Press 2 for Subtraction -----");
Console.WriteLine("Press 3 for Multiplication ****");
Console.WriteLine("Press 4 for Division ////");
Console.WriteLine("Press 5 for calculating the Perimeter of a rectangle (x/y)");
Console.WriteLine("Press 6 for calculating the Volume of an object (x/y/z)");
Console.WriteLine("Press 7 for calculating the standard deviation of a set of 10 numbers");
decision = int.Parse(Console.ReadLine());
if (decision < 1 || decision > 7)
{
decision = 0;
Console.WriteLine("Please select a function from the list. Press Enter to reselect.");
Console.ReadLine();
}
else
{
break;
}
}
return decision;
}
When I try to use decision up in Main() it says "The name decision does not exist in the current context".
I'm stumped and tried googling it to no avail.
Cheers
SUCCESS!
Return the value from Introduction. The value is local to the method and to use it elsewhere you need to return it and assign to a local variable. Alternatively, you could make decision a static class variable, but that's not a particularly good practice, at least in this case. The Introduction method (not a particularly good name, IMO, it should probably be GetCalculationType() since that is what it is doing) typically shouldn't have any side-effects.
public static void Main( string[] args )
{
int decision = Introduction();
...
}
public static int Introduction()
{
int decision = 0;
...
return decision;
}
Main() is the entry point for your app. It then calls your method Introduction() which adds a new stack frame on the stack. Because you declare the decision variable inside your Introduction method, the Main method has no knowledge of it.
If you instead declare your decision variable outside both methods, you should be able to reference it from either:
int decision;
static void Main(string[] args)
{
// code here
}
static void Introduction()
{
// code here
}
You can't use the decision variable in main since it is local to the function Introduction.
You could make decision a static class variable but better would be to return the value from Introduction and assign it to a local variable in main.