I'm learning C# and i'm having problems with variable scope in my simple console program.
The program runs perfectly so far except I know I will encounter issues when trying to reference variables previously instantiated.
I have tried to change methods from static to non static and also applied public/private access but to no avail.
I just need a nudge in the right direction, hope someone can help!
The error message i'm getting is :
Error 1 An object reference is required for the non-static field, method, or property 'ConsoleApplication2.Program.game()'
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class Program
{
int numberToGuess;
int numberGuessed;
int triesRemaining;
public void game()
{
Console.WriteLine(" ==Welcome to Guess My Number== \n");
Console.WriteLine("Player 1: Please enter your number to guess between 1 and 20: \n");
numberToGuess = int.Parse(Console.ReadLine());
Console.WriteLine("Player 2, please enter your first guess, you have 7 tries: \n");
numberGuessed = int.Parse(Console.ReadLine());
if (numberGuessed == numberToGuess)
{
correct();
}
else
{
incorrect();
}
}
public void correct()
{
Console.WriteLine("Congratulations, the number was in fact " + numberToGuess);
}
public void incorrect()
{
}
static void Main(string[] args)
{
game();
}
}
}
instance members (those not marked with the static keyword) exist once per object instance. Every instance of an object gets its own copies of them.
static members, on the other hand, exist once for the entire class and are shared by all object instances.
So, If you've got a class:
class Foo
{
public static int Alpha { get ; set ; }
public int Bravo { get ; set ; }
}
No matter how many instances of your Foo class are created, there is only one instance of Alpha. Any instance method or property can access a static member directly.
Instance members, since they exist on a per-instance basic, require an object instance to reference them. If you add some methods to the Foo class:
public static int DoSomething()
{
return Alpha * 3 ;
}
is perfectly valid — the method is static and the member is static. Ditto for an instance method:
public int DoSomethingElse()
{
return Alpha * 3 ;
}
Something like this will fail:
public static int AndNowForSomethingCompletelyDifferent()
{
return Alpha * 3 + Bravo ;
}
Bravo can't be referenced here without a reference to an instance of Foo. This will work however:
public static int AndNowForSomethingCompletelyDifferent( Foo instance )
{
return Alpha * 3 + instance.Bravo ;
}
As will this:
public int AndNowForSomethingCompletelyDifferent()
{
return Alpha * 3 + Bravo ;
}
Since the method is non-static (an instance method), it has an implicit reference (this) to its instance of Foo. The above is exactly equivalent to
public int AndNowForSomethingCompletelyDifferent()
{
return Alpha * 3 + this.Bravo ;
}
In your case, you could instantiate the class Program in your Main() method:
public static void Main( string[] args )
{
Program p = new Program() ;
p.game() ;
return ;
}
Or you could mark your methods game(), correct() and incorrect() as static, just as the Main() method is marked.
Hope this helps!
static methods/fields belong to the user-defined type, not the instance.
For example, if you look at this piece of code:
public class MyClass
{
public static void Foo()
{
}
}
the Foo() method, is not accessed from an instance of MyClass. Since it is static, you access it from the user-defined type itself. Ex:
public class Program
{
static void Main(String[] args)
{
MyClass.Foo();
}
}
Since Main() is static, you can only reference static methods or variables inside it (this excludes methods referenced from local instance variables).
In your code, the method game() and the fields/methods being called/invoked by game are not static, therefore you would only be able to access it via an object instance. Of course, making game() and all the other fields/methods static would result in a working piece of code.
For more information on static types, look here: http://msdn.microsoft.com/en-us/library/98f28cdx.aspx
I have gone on to complete the methods and it seems to be working great!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class Program
{
int numberToGuess;
int numberGuessed;
int triesRemaining = 7;
string playAgain;
string player1, player2;
public void game() //Initiates the game instance
{
Console.WriteLine(" ==Welcome to Guess My Number== \n");
Console.WriteLine(" Player 1, Please enter your name: \n");
player1 = Console.ReadLine();
Console.Clear();
Console.WriteLine(" ==Guess My Number== \n");
Console.WriteLine("Hello " + player1 + " : Please enter your number to guess between 1 and 20: \n");
numberToGuess = int.Parse(Console.ReadLine());
Console.Clear();
Console.WriteLine(" ==Guess My Number== \n");
Console.WriteLine(" Player 2, Please enter your name: \n");
player2 = Console.ReadLine();
Console.Clear();
Console.WriteLine("Hello " + player2 + " please enter your first guess, you have 7 tries: \n");
numberGuessed = int.Parse(Console.ReadLine());
if (numberGuessed == numberToGuess)
{
Console.WriteLine("Congratulations, the number was in fact " + numberToGuess);
newGame();
}
else
{
incorrect();
}
}
public void incorrect() //Method for dealing with incorrect answers
{
for (int x = 0; x < 6; x++)
{
triesRemaining--;
Console.WriteLine("Incorrect, you have " + triesRemaining + " tries remaining \n");
Console.WriteLine(player2 + ", please enter your next guess: \n");
numberGuessed = int.Parse(Console.ReadLine());
if (numberGuessed == numberToGuess)
{
Console.WriteLine("Congratulations, the number was in fact " + numberToGuess);
newGame();
}
else {
//Do nothing
}
}
Console.WriteLine("You have used up all your tries! You have failed. The number was: " +numberToGuess + "\n");
newGame();
} //Method for dealing with incorrect answers
public void newGame() //Method that gives the user the option to start a new game instance
{
Console.WriteLine("Would you like to play again? Type yes or no: \n");
playAgain = Console.ReadLine();
playAgain = playAgain.ToLower();
if (playAgain == "yes")
{
Console.Clear();
game();
}
else if (playAgain == "y")
{
game();
}
else
{
//Do nothing
}
}
static void Main(string[] args)
{
new Program().game();
}
}
}
Related
I am working on a complex project that is related to threading. Here is the simplest interpretation of my problem. Below is the code here are 3 functions excluding the main function. All functions are running in multi-threads. There is a while loop in all functions. I just want to get variable "i" and "k" from "func1" and "func2" respectively and use it in "func3". These variables are updated in the while loop.
This is the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Threading
{
class Program
{
public static void func1() //How can I get the variable "i" from the while loop. Note: This function is running in thread.
{
int i = 1;
while (true)
{
Console.WriteLine("Func1: " + i);
i++;
}
}
public static void func2() //How can I get the variable "k" from the while loop. Note: This function is running in thread.
{
int k = 1;
while (true)
{
Console.WriteLine("Func2: " + k);
k++;
}
}
public static void func3() //After getting variables from func1 and func2 I want them to use in function 3.
{
while (true)
{
int sum = i + k;
Console.WriteLine("the sum is" + sum);
}
}
public static void Main(string[] args)
{
Thread t1 = new Thread(func1);
Thread t2 = new Thread(func2);
Thread t3 = new Thread(func3);
t1.Start();
t2.Start();
t3.Start();
}
}
}
You probably need to hoist the i and k from local variables to private fields of the Program class. Since these two fields will be accessed by more than one threads without synchronization, you should also declare them as volatile:
private static volatile int i = 1;
private static volatile int k = 1;
public static void func1()
{
while (true)
{
Console.WriteLine("Func1: " + i);
i++;
}
}
public static void func2()
{
while (true)
{
Console.WriteLine("Func2: " + k);
k++;
}
}
public static void func3()
{
while (true)
{
int sum = i + k;
Console.WriteLine("the sum is" + sum);
}
}
The pattern of access makes the use of volatile a bit wasteful though. The func1 is the only method that changes the i, so reading it with volatile semantics inside this method is pure overhead. You could use instead the Volatile.Read and Volatile.Write methods for finer control:
private static int i = 1;
private static int k = 1;
public static void func1()
{
while (true)
{
Console.WriteLine("Func1: " + i);
Volatile.Write(ref i, i + 1);
}
}
public static void func2()
{
while (true)
{
Console.WriteLine("Func2: " + k);
Volatile.Write(ref k, k + 1);
}
}
public static void func3()
{
while (true)
{
int sum = Volatile.Read(ref i) + Volatile.Read(ref k);
Console.WriteLine("the sum is" + sum);
}
}
I am trying to raed the value of userInput variable in my parent class which is stored in my child class, but I can't reach it and I get many errors one after one after each try. Can you please help me?
This is apart of my code:
//Child class
class tictactoe
{
public void beginGame()
{
ConsoleKeyInfo gebruikerInvoer;
gebruikerInvoer = Console.ReadKey();
//Rest of code
}
}
//Parent class
namespace Quizz
{
class Program
{
public static void Main(string[] args)
{
tictactoe minigame1 = new tictactoe();
while (minigame1.gebruikerInvoer)
{
//Rest of code
}
}
}
}
This is the error I get
'tictactoe' does not contain a definition for 'gebruikerInvoer' and no accessible extension method 'gebruikerInvoer' accepting a first argument of type 'tictactoe' could be found (are you missing a using directive or an assembly reference?)
I think that I will need to make a method to call it from the parent, if so: what type should I give since the variable is a ConsoleKeyInfo that is later converted to string?
gebruikerInvoer.KeyChar.ToString()
As the comments have made apparent, you need to first make the variable visible to the outside world. Local variables are always hidden from other classes. So lets fix this first:
class tictactoe
{
public ConsoleKeyInfo gebruikerInvoer; //Make public and move owner to class not method
public void beginGame()
{
gebruikerInvoer = Console.ReadKey();
//Rest of code
}
}
//Parent class
namespace Quizz
{
class Program
{
public static void Main(string[] args)
{
tictactoe minigame1 = new tictactoe();
while (minigame1.gebruikerInvoer) //CS0029 ConsoleKeyInfo cannot be implicitly converted to type Bool
{
//Rest of code
}
}
}
}
Moving on from there you need to define a statement to test the variable's value in a way that can return a true or false statement to use a while loop. To fix that we can do something like this:
class tictactoe
{
public ConsoleKeyInfo gebruikerInvoer;
public void beginGame()
{
gebruikerInvoer = Console.ReadKey();
//Rest of code
}
}
//Parent class
namespace Quizz
{
class Program
{
public static void Main(string[] args)
{
tictactoe minigame1 = new tictactoe();
bool minigameRun = minigame1.gebruikerInvoer.KeyChar == 't'
? true : false; //Assign a true value if the user entered the letter 't', else false
while (minigameRun) //Runs rest of code while minigameRun is true
{
//Rest of code
}
}
}
}
Then to escape the while loop you can use return, break, or upon some condition change the local bool minigameRun to false. The bool is initially assigned in this code using the ?: operator. You can read more about its use here
I'm trying to write a program that consists of some items (only 2 of them for now). It doesn't show any errors in the console, but when I try to call the Main function more than once, it doesn't execute the loops inside. Here's the code by the way.
public static class Program
{
public static string input = Convert.ToString(Console.ReadLine());
public static int health = 100;
public static int energy = 100;
public static void Main()
{
Console.WriteLine("This is a game used for testing items");
Console.WriteLine("Would you like to use items or get them? (Typing in status shows the value of your health and energy)");
if (Program.input == "get")
{
Items.GetItems();
}
if (Program.input == "use")
{
ItemUser();
}
if (Program.input == "status")
{
StatusChecker();
}
}
public static void StatusChecker()
{
Console.WriteLine("Your health is " + Program.health);
Console.WriteLine("Your energy is " + Program.energy);
}
public static void ItemUser()
{
Console.WriteLine("What do you want to use?");
string useChecker = Convert.ToString(Console.ReadLine());
if (useChecker == "healthPotion")
{
health += 100;
Items.healthPotion--;
}
if (useChecker == "energyDrink")
{
energy += 100;
Items.energyDrink--;
}
}
}
public static class Items
{
public static int healthPotion = 0;
public static int energyDrink = 0;
public static void GetItems()
{
Console.WriteLine();
string itemChecker = Convert.ToString(Console.ReadLine());
if ( itemChecker == "health potion")
{
healthPotion++;
Program.Main();
}
if (itemChecker == "energy drink")
{
energyDrink++;
Program.Main();
}
}
So I wanted the program to get the values after updating them, but it just stops after I call Main method more than once. Can anyone help me?
(I'm not that great at coding so I couldn't make really efficient code)
You don't have any loops inside your Main method and every time you run the application you start from scratch and each of your variables contain initial values. If I get right what you're trying to achieve, I would suggest you to write the Main method like this to have loop which will ask a user for a command until the user enters "quit":
static void Main(string[] args)
{
Console.WriteLine("This is a game used for testing items");
while (true)
{
Console.WriteLine("Would you like to use items or get them? (Typing in status shows the value of your health and energy)");
string userAnswer = Console.ReadLine();
if (userAnswer == "quit") break;
if (userAnswer == "get")
{
Items.GetItems();
}
if (userAnswer == "use")
{
ItemUser();
}
if (userAnswer == "status")
{
StatusChecker();
}
}
}
I noticed also that when you call ItemUser method you update static variables of your Items class, but in the StatusChecker method you write to the console variables of your Program class. They are actually different, so I think in your StatusChecker method you may want do the following:
public static void StatusChecker()
{
Console.WriteLine("Your health is " + Items.health);
Console.WriteLine("Your energy is " + Items.energy);
}
You are assigning a variable here:
public static string input = Convert.ToString(Console.ReadLine());
So the next time you call your "Main" method it will use the value you typed in the first time your app executed. If you want it to ask each time you'll need to do something like this:
public static void Main()
{
input = Convert.ToString(Console.ReadLine());
...
}
Another thing is that it can exit after the first call if you type in i.e. "status".
Issue number 3 is that this is not the "nice" way to write a program. The Main method is supposed to be executed when your app starts as it is the entry point (more on that here).
I am trying to 'share' variables between methods in C#. I am quite new to C#, I know there's no such thing as a 'global variable' and I'm not quite sure how to correctly use static variables.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectOne
{
static bool tooHigh;
static internal waistMeasurment;
class Main
{
static void Main(string[] args)
{
GetVariables();
}
public static void GetVariables() //This method gets the users height & waist measurments
//and calls the 'ValidateWaist' and 'ValidateHeight' methods for validation
{
Console.Write("What is your waist measurment? "); //This prints a string prompting the user to input their waist measurment
waistMeasurment = Console.ReadLine(); //This writes the users input under the string 'waistMeasurment'
ValidateWaist();
if tooHigh ==true
{
waistMeasurment = Console.ReadLine();
ValidateWaist();
}
}
public static void ValidateWaist() //This method validates the user input so that it fits within the minimum bound
{
if (waistMeasurment < 60) //Checks the lower bound of the waist limit
{
Console.Write("Your waist measurment must be above 59cm? "); //Output error feedback
tooHigh = true;
}
else
{
tooHigh = false;
}
}
}
}
Im having issues with the tooHigh and waistMeasurment
C# is an Object-Oriented Programming Language, which means it consists of namespaces, that hold classesand structs, which hold fields and properties (so, variables) and methods.
You're absolutely right, there are no global variables in C#. Although, you could hack together a class with a static variable and use it as a global, it's best to keep all the variables local and under control.
What you want to achieve, is to place the two variables (tooHigh and waistMeasurment) within the static Main class as static variables.
You also don't use if statements in the style of Python and internal was invented for methods, not variables. According to your code, you are looking for the type of integer, since later on, you are checking whether the variable waistMeasurment is less than 60. In order to do this, you first have to cast the variable to an integer. The proper way to this, is with the int.TryParse method.
namespace ProjectOne
{
class Main
{
static bool tooHigh;
static int waistMeasurment;
static void Main(string[] args)
{
GetVariables();
}
public static void GetVariables() //This method gets the users height & waist measurments
//and calls the 'ValidateWaist' and 'ValidateHeight' methods for validation
{
Console.Write("What is your waist measurment? "); //This prints a string prompting the user to input their waist measurment
int.TryParse(Console.ReadLine(), out waistMeasurment); //This writes the users input under the string 'waistMeasurment'
ValidateWaist();
if (tooHigh)
{
int.TryParse(Console.ReadLine(), out waistMeasurment);
ValidateWaist();
}
}
public static void ValidateWaist() //This method validates the user input so that it fits within the minimum bound
{
if ((int)waistMeasurment < 60) //Checks the lower bound of the waist limit
{
Console.Write("Your waist measurment must be above 59cm? "); //Output error feedback
tooHigh = true;
}
else
{
tooHigh = false;
}
}
}
}
Static can be used to share variable but need to be declared inside Class, there were some more errors in your program, I have modified your program you can use it and debug it for learning
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static bool tooHigh;
static int waistMeasurment;
static void Main(string[] args)
{
GetVariables();
}
public static void GetVariables() //This method gets the users height & waist measurments
//and calls the 'ValidateWaist' and 'ValidateHeight' methods for validation
{
Console.Write("What is your waist measurment? "); //This prints a string prompting the user to input their waist measurment
int.TryParse(Console.ReadLine(), out waistMeasurment); //This writes the users input under the string 'waistMeasurment'
ValidateWaist();
if (tooHigh == true)
{
int.TryParse(Console.ReadLine(), out waistMeasurment); ;
ValidateWaist();
}
}
public static void ValidateWaist() //This method validates the user input so that it fits within the minimum bound
{
if (waistMeasurment < 60) //Checks the lower bound of the waist limit
{
Console.Write("Your waist measurment must be above 59cm? "); //Output error feedback
tooHigh = true;
}
else
{
tooHigh = false;
}
}
}
}
As stated in the comments you have to change your code in order to place the variables inside a Type:
What you've got:
namespace ProjectOne
{
static bool tooHigh;
static internal waistMeasurment;
class Main
{
//your code
}
}
What you have to write:
namespace ProjectOne
{
class Main
{
static bool tooHigh;
static internal waistMeasurment;
//your code again
}
}
I looked all over the internet for solutions to this but none of them work:
public static void Main (string[] args)
{
Console.Write ("What is your name: ");
string input = Console.ReadLine ();
sayHi ();
}
public static string sayHi() {
Console.WriteLine ("Hello {0}!", input);
}
I don't need an answer that will help me do this without a global variable, that's not what I'm looking for
When I execute this I get this error:
The name 'input' does not exist in the current context
I tried making one of the lines
public string input = Console.ReadLine ();
but I get
Unexpected symbol 'public'
I tried
static string input = Console.ReadLine ();
But I get
Unexpected symbol 'static'
This
public static string input = Console.ReadLine ();
gives me
Unexpected symbol 'public'
I don't want a solution that doesn't use global variables
You should declare the variable outside of the Main method in the class containing both functions:
private static string input;
public static void Main (string[] args)
{
Console.Write ("What is your name: ");
input = Console.ReadLine ();
sayHi ();
}
public static string sayHi() {
Console.WriteLine ("Hello {0}!", input);
}
In this case the scope of the input variable will be the containing class and you can access it from all methods within this class.
There is no such thing as global variables in C#. This will do the trick for you. You could also try the static class with static members solution to simulate something like global variables, but that still won't be a global variable.
Try this (you're using an attribute in the class in this solution, it will be "global" inside this class)
public class YourClass{
private static string _input;
public static void Main (string[] args)
{
Console.Write ("What is your name: ");
_input = Console.ReadLine ();
sayHi ();
}
public static string sayHi() {
Console.WriteLine ("Hello {0}!", _input);
}
}
You can use Static class
static class Global
{
private static string _gVariable1 = "";
public static string Variable1
{
get { return _gVariable1 ; }
set { _gVariable1 = value; }
}
}
And you can use it like
Global.Variable1 = "any string value"