Variable declaration and scope in C# - c#

I'm new to C# and have some trouble with the variable scope.
if(number > 10)
{
int someNr = 5;
}
else
{
/* .... */
}
if(number2 < 50)
{
someNr = 10; /* PRODUCES AN ERROR */
}
else
{
/* ........ */
}
I know that if number is not > 10 then someNr will not be declared as int. But should I wrote two times int someNr? What if both if are true? Double declaration? Is this a problem should I declare the variable outside the if?
Class variables
PHP
class TEST {
private $test = 'test';
private function testVariable(){
/* Not declared */
echo $test;
}
private function testVariable2(){
/* echo 'test' */
echo $this->test;
}
}
C#
class TEST {
private string test = "test";
private void testVariable(){
/* takes the value of class variable test */
test;
}
private function testVariable2(){
/* takes also the value of class variable 'test' */
this.test;
}
}
But what if
C#
class TEST {
private string test = "test";
private void testVariable(){
string test = "somethingOther";
Console.WriteLine(test);
}
}
test is "test" or "somethingOther"?
Which has the priority? The class variable or the local-method variable?

To set the variable inside an if statement you should declare it outside the if statement, otherwise it will be a local variable only available inside the if statement:
int someNr;
if(number > 10)
{
someNr = 5;
}
else
{
/* .... */
}
if(number2 < 50)
{
someNr = 10;
}
else
{
/* ........ */
}
Note: You also need to set some value to the variable in the else blocks, or set an initial value when you define it, otherwise it's not known to always have a value.
In your class TEST the local variable will shadow the class member:
class TEST {
private string test = "test"; // this is a member of the class
private void testVariable(){
string test = "somethingOther"; // this is a local variable that shadows the class member
Console.WriteLine(test); // this will use the local variable, it can't see the class member
}
}

your first example produces an error, because someNr is only defined within the scope of the if statement. You must re-define it in your second if, declaring it as an int.
In your second example, the correct syntax would be Console.WriteLine(test);. Your output would be 'somethingOther', as the test in the inner scope will be used.

Example of Method Scope -- variable someNr is declared within the method (along with number2) and is therefore accessible throughout the method:
public class IntegersTestScope
{
public void TestIntegers(int number)
{
int number2 = 0;
int someNr = 0;
number2 += number;
if (number > 10)
{
someNr = 5;
}
else
{
/* .... */
}
if (number2 < 50)
{
someNr = 10; /* This will no longer PRODUCE AN ERROR */
}
else
{
/* ........ */
}
Console.WriteLine("someNr={0}", someNr.ToString());
}
}
Example of Class Scope -- variable _someNr is declared within the class and are therefore accessible to all methods with that class (Note: variable _someNr is prefixed with underscore character '_' as a naming convention only to denote variable global to class and is not required for code to work):
public class IntegersTestScope
{
private int _someNr = 0;
public void TestIntegers(int number)
{
int number2 = 0;
number2 += number;
if (number > 10)
{
_someNr = 5;
}
else
{
/* .... */
}
if (number2 < 50)
{
_someNr = 10; /* This will no longer PRODUCE AN ERROR */
}
else
{
/* ........ */
}
Console.WriteLine("someNr={0}", _someNr.ToString());
}
}

Related

I got this error CS0103 and I don't know if this is from C# extension or if I forget to put something

I don't know if this is an error with the C# extension or I just forgot something.
I was trying to make a health base system so I convert into a string to print the number then back to int, to its original form.
FYI this some of my code, not all of it another thing I know their other forms but it wasn't looking for.
Example 1
example 2
class Conehead_Wizzard
{
public string name;
public string ConeHead_Powerful_spells;
public int slots;
public float Level_Up;
public int Player_Health;
public int Chance;
public int b;
public int c;
public Conehead_Wizzard(string _name, string _ConeHead_Powerful_spells,
int _Player_Health)
{
name = _name;
ConeHead_Powerful_spells = _ConeHead_Powerful_spells;
slots = 5;
Level_Up = 1.2f;
Player_Health = 1000;
b = 100;
void Damage_Chance ()
{
Random Chance_ = new Random();
int Chance = Chance_.Next(0, 100);
if (Chance > 99)
{
System.Console.WriteLine(Player_Health - b);
System.Console.WriteLine("you lost" + Player_Health + "of your health");
Player_Health--;
string a = Convert.ToString(Player_Health);
}
else
{
System.Console.WriteLine("Miss!, next player");
c = Convert.ToInt16(Player_Health);
}
}
}
}
class Program
{
static void Main(string[] args)
{
Conehead_Wizzard wizzard = new Conehead_Wizzard("Cone_Head ",
"The Cone of time &" + " Cone of shield", Player_Health);
}
}
You haven't declared the variable Player_Health in the Main method. Did you maybe intend to do something as follows:
static void Main(string[] args)
{
int Player_Health = 1000;
Conehead_Wizzard wizzard = new Conehead_Wizzard("Cone_Head ", "The Cone of time &" + " Cone of shield", Player_Health);
}
Although this should allow you to compile, be aware, the constructor isn't using the value passed into _Player_Health. It just sets wizzard.Player_Health to 1000. If you want to use it, you need to change your constructor to something like this:
public Conehead_Wizzard(string _name, string _ConeHead_Powerful_spells, int _Player_Health)
{
name = _name;
ConeHead_Powerful_spells = _ConeHead_Powerful_spells;
slots = 5;
Level_Up = 1.2f;
Player_Health = _Player_Health;
b = 100;
}

C#: Storage of instances in the class; get NullReferenceException when trying to get theirs value

I am a new to OOP and C#. Here is a small experiment I made:
Using System;
class A
{
public int X { get; set; }
public static A[] a = new A[10];
public static int i = 0;
public A()
{
this.X = -2;
}
public A(int x)
{
this.X = x;
}
public static void Add(A b)
{
if (i < 10) a[i] = b;
i++;
return;
}
public void Reveal()
{
Console.WriteLine(X);
}
public static void Show()
{
for (int j=0; j<=10; ++j)
{
a[j].Reveal();
}
}
}
I tried creating a class that has its instances stored inside, up to 10 objects. When invoke the A.Show() a NullReferenceException is thrown: "Object reference not set to an instance of an object." As I guess, it must be the object a[j] is created, then destroyed immediately. So it give a[j] a null value, hence the result?
*This is my main method:
int val = 0;
while (val != -1)
{
Console.Write("create a new object. new value: ");
val = Console.ReadLine();
A a = new A(val);
A.Add(a);
};
A.Show();
Console.ReadKey();
return;
Please pay attention to the upper bound condition of the loop:
for (int j=0; j<=10; ++j)
{
a[j].Reveal();
}
array a has 10 items assigned,but this code shows you have 11 items beginning from 0 to 10, so change it to just lower than 10.And also try to compare
So the correct code can be as follows :
public static void Show()
{
for (int j = 0; j < 10; ++j)
{
a[j]?.Reveal();//Or if(a[j] != null)
}
}
and also make amendment to line that reads the input of client,that must be as follow:
val = int.Parse(Console.ReadLine());//If you are sure that the input
is truly convertible to int,or
int.TryParse(Console.ReadLine() , out int value);
if(value != 0)
{
val = value;
A a = new A(val);
A.Add(a);
}
else
{
throw new Exception();
}
You're incrementing i before assigning a[i], so a[0] is null because it will always start initializing a at 1.
Try changing the add method to this:
public static void Add(A b)
{
if (i < 10)
{ //braces are important for readability
a[i] = b;
}
i++;
return;
}

Can't figure out why Object reference is null

Working on a program for class, and am about 95% complete, but have run into a roadblock. I've got a Flight class that holds information about the flight, as well as a seating chart. Using a windows form listbox to select from the flight objects I created by reading from a text file. I can get values for every property from the class object, except for one, SeatChart.
Here's the pertinent code in the main program:
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = (Flight)lstFlights.SelectedItem;
DisplayNewFlightChart();
}
private void DisplayNewFlightChart()
{
int seats = curFlight.Rows * curFlight.Seats;
lstSeatingChart.Items.Clear();
string[] seatChart = curFlight.SeatChart;
for (int x = 0; x <= seats; x++)
{
lstSeatingChart.Items.Add("Seat " + (x + 1) + " " + seatChart[x]);
}
}
And here is the code from the class:
class Flight
{
private string mPlane;
private string mDepartureTime;
private string mDestination;
private int mRows;
private int mSeats;
private string[] mSeatChart;
public Flight()
{
}
// Create the overloaded Constructor
public Flight(string planeType, string departureTime,
string destination, int numRows,
int numSeatsPerRow)
{
this.Plane = planeType;
this.DepartureTime = departureTime;
this.Destination = destination;
this.Rows = numRows;
this.Seats = numSeatsPerRow;
this.SeatChart = mSeatChart;
mSeatChart = new string[Rows * Seats];
for (int seat = 0; seat <= mSeatChart.GetUpperBound(0); seat++)
{
mSeatChart[seat] = "Open";
}
}
public string Plane
{
get { return mPlane; }
set { mPlane = value; }
}
public string DepartureTime
{
get { return mDepartureTime; }
set { mDepartureTime = value; }
}
public string Destination
{
get { return mDestination; }
set { mDestination = value; }
}
public int Rows
{
get { return mRows; }
set { mRows = value; }
}
public int Seats
{
get { return mSeats; }
set { mSeats = value; }
}
public string[] SeatChart
{
get { return mSeatChart; }
set { mSeatChart = value; }
}
public void MakeReservation(string passName, int seat)
{
bool seatTaken = false;
if (mSeatChart[seat] != "Open") seatTaken = true;
if (passName != "" && seatTaken == false)
{
mSeatChart[seat] = passName;
}
else
{
MessageBox.Show("Please Enter a Passenger Name, in an unreserved seat");
}
}
It's telling me the curFlight.SeatChart is null, even though I can pull .Rows and .Seats from the curFlight just fine. I have no clue why .SeatChart is messing up. lstFlights is the list of flight objects pulled from the text file, and lstSeatingChart is where I want to display a list of seats.
You are setting SeatChart to mSeatChart, which is null at that time. So no reference to an object is made for this.SeatChart.
After that you initialize mSeatChart and fill it.
You should move setting this.SeatChart after initializing mSeatChart.
mSeatChart = new string[Rows * Seats];
this.SeatChart = mSeatChart;
Edit:
In addition, SeatChart is the property and mSeatChart is the member variable. SeatChart will be used to expose mSeatChart, so it's really weird to set SeatChart with mSeatChart. So weird that I didn't even think you were doing that.
So in your case leave the following out in the constructor:
this.SeatChart = mSeatChart;
I think the actual cause of your issue is somewhere else in the code, where you initiate Flight and fill the list. If I understand correctly you get a null reference error on the concatenation in the for loop?
string[] seatChart = curFlight.SeatChart;
for (int x = 0; x <= seats; x++)
{
lstSeatingChart.Items.Add("Seat " + (x + 1) + " " + seatChart[x]);
}
Check where you initate each Flight object. I bet you are using the empty constructor: new Flight()
Remove the empty constructor, because you don't expect empty values apparently. And if you really need the empty constructor then either initiate all member variables as expected or perform a null check wherever you want to use them.
And once you found the cause, make sure you change the for loop to
for (int x = 0; x < seats; x++)
since you are checking for the number of seats and do a zero-based loop. If x = seats you would have performed the loop seats + 1 times (rows*seats + 1).
If your code relies on a particular property never being null, you need to make sure it is initialized in all constructors.
Based on the logic of your class, I would suggest you shouldn't have a parameter less constructor. It doesn't make sense to have a flight that didn't have a known number of seats (in your implementation at least).
Also some style things.
You don't need to declare your private instance variables. Just use
public string destination {get; set;}
Declare "open" as a class constant and use that constant rather than the hard coded string value.

C# Constructors and Contexes

I am trying to create a console application that converts centimeters to meters
Here are my objectives
Store number of centimeters entered in an attribute
Use a default constructor to store zero in the attribute that stores the number of centimeters meters entered
Use a primary constructor to accept and store number of centimeters entered.
A function call getMeters to return the number of meters
A function called Remainder to get the number of centimeter remanding after conversion
A function called Printout that will display the results
The application should carry on accepting values for conversion until the user decides to end it.
What I have so far:
using System;
namespace Conv
{
public class Centimeter
{
public int cmvar;
public Centimeter()
{
cmvar = 0;
}
}
//primary const to be added
public class MeterToCenti
{
public static void Main()
{
char choice;
char n = 'n';
do
{
Console.WriteLine("Do you want to continue? (y/n)");
//choice = Console.ReadLine();
choice = Console.ReadKey().KeyChar;
Centimeter c = new Centimeter();
Console.WriteLine("enter value in centimeters");
c.cmvar = int.Parse(Console.ReadLine());
Printout();
}
while(choice.CompareTo(n) == 0);
}
public static void getMeterst()
{
int meters = c.cmvar / 100;
}
public static void Remainder ()
{
int cmremain = c.cmvar % 100;
}
public static void Printout()
{
Console.WriteLine("{0} Meters and {1} Centimeters", meters, cmremain);
}
}
}
I am getting errors regarding:
prog.cs(24,5): warning CS0168: The variable `meters' is declared but never used
prog.cs(41,11): error CS0103: The name `c' does not exist in the current context
prog.cs(41,2): error CS0103: The name `meters' does not exist in the current context
prog.cs(47,24): error CS0103: The name `c' does not exist in the current context
prog.cs(53,61): error CS0103: The name `meters' does not exist in the current context
prog.cs(53,69): error CS0103: The name `cmremain' does not exist in the current contex
Any help would be appreciated.
In some programming languages, a context is usually defined by { and }, meaning that given this:
{
int a = ...
}
a exists specifically within that block. Assuming that no other variable named a has been declared outside the braces, doing something like so:
{
int a = ...
}
print(a)
Will result in a fault, since a no longer exists.
In your case for instance, you are declaring the following variable: Centimeter c = new Centimeter();. Notice that this is enclosed within the do...while scope, so it exists only in there. Thus, when you try to access your variable from another method, which has its own scope, you get the exception you are getting.
To start solving the issue, you should move the 3 methods getMeterst, Remainder and Printout in their appropriate class, which is Centimeter.
I would recommend you start by looking at some tutorials, since you have other issues with your code.
As pointed out by #user2864740, different languages treat scopes differently. Taking Javascript in consideration:
function hello()
{
{
var i = 44;
}
{
alert(i);
}
}
Yields an alert with the value of 44.
However, the code below does not compile in C#:
private static void Hello()
{
{
int i = 0;
}
{
Console.WriteLine(i); //The name i does not exist in the current context.
}
}
you've got a lot of issues with scope in your code, when you declare something, it can (as a rule) only be accessed inside whatever set of brackets you declare it in, so when you try and access c and cmremainand things like that without specifying their location or accessing them correctly you get errors like this.
I have working code below, but feel free to ask any extra questions as to 'why' this works.
using System;
namespace Conv
{
public class Centimeter
{
public int cmvar;
public Centimeter()
{
cmvar = 0;
}
}
//primary const to be added
public class MeterToCenti
{
public static void Main()
{
char choice;
char n = 'n';
do
{
Centimeter c = new Centimeter();
Console.WriteLine("enter value in centimeters");
c.cmvar = int.Parse(Console.ReadLine());
Printout(c);
Console.WriteLine("Do you want to continue? (y/n)");
choice = Console.ReadKey().KeyChar;
Console.WriteLine();
}
while (choice != n);
}
public static int getMeters(Centimeter c)
{
int meters = c.cmvar / 100;
return meters;
}
public static int Remainder(Centimeter c)
{
int cmremain = c.cmvar % 100;
return cmremain;
}
public static void Printout(Centimeter c)
{
Console.WriteLine("{0} Meters and {1} Centimeters", getMeters(c), Remainder(c));
}
}
}
you need to learn oriented object programming before programming any oop language.
Basic is good but polute your mind by not thinking object, but sequencial...
Here is your code fixed
using System;
namespace Conv
{
public class Centimeter
{
public int cmvar;
public Centimeter()
{
cmvar = 0;
}
public Centimeter(int mm)
{
cmvar = mm;
}
public int getMeterst()
{
return cmvar / 100;
}
public int Remainder()
{
return cmvar % 100;
}
public void Printout()
{
Console.WriteLine("{0} Meters and {1} Centimeters", this.getMeterst(), this.Remainder());
}
}
public class MeterToCenti
{
public static void Main()
{
char choice;
char n = 'n';
do
{
Console.WriteLine("Do you want to continue? (y/n)");
choice = Console.ReadKey().KeyChar;
Console.WriteLine(); // for pure design needs
Centimeter c = new Centimeter();
Console.WriteLine("enter value in centimeters");
c.cmvar = int.Parse(Console.ReadLine());
c.Printout();
}
while (choice != n);
}
}
}

The get and set property appears to be ignored (C#)

I'm trying to modify the "set" portion, but these changes don't seem to take place at all. Here is the basic code that shows the same results:
class Class1
{
private int num;
public Class1(int number)
{
num = number;
}
public int getNumber
{
get
{
return num;
}
set
{
if (value > 0)
num = value;
else
num = 0;
}
}
}
In here, I want to make any negative value a 0.
class Program
{
static void Main(string[] args)
{
Class1 c1 = new Class1(10);
Class1 c2 = new Class1(-10);
Console.WriteLine(c1.getNumber);
Console.WriteLine(c2.getNumber);
Console.ReadLine();
}
}
The result gives me
10
-10
I've tried using
set
{
num = 100;
}
yet there's still no change in the results. I've tried double checking with the book I'm using, and there's no difference that I can see. I'm using Visual Studio 2012 if it means anything.
Your code is not calling set portion of your property. Because, you are only calling constructor. And in your constructor you are only setting tha value for the backing field variable(num).
Also, by convention, your class members names are not appropriate.
Change it as:
num -> number getNumber -> Number
Try this:
Class1 c1 = new Class1();
c1.Number = -10; // The set accessor is invoked here
int myNumber = c1.Number; // The get accessor is invoked here
If you want to invoke set accessor through your constructor, then change your constructor as:
public Class1(int number)
{
Number = number;
}
Then it will invoke set accessor properly:
Class1 c1 = new Class1(10); // The set accessor will be invoked
And don't forget to change your class implementation as:
class Class1
{
private int number;
public int Number
{
get { return number; }
set
{
if (value > 0)
number = value;
else
number = 0;
}
}
// If you do provide a constructor (any constructor with any signature),
// the parametrless constructor will not be generated
public Class1()
{
}
public Class1(int number)
{
Number = number;
}
}
Read this from msdn for additional information.
Try this:
class Class1
{
private int num;
public Class1(int number)
{
Number = number;
}
public int Number
{
get
{
return num;
}
set
{
if (value > 0)
num = value;
else
num = 0;
}
}
}
You hadn't implented it correctly. Actually a better implmentation would be the following:
class Class1
{
// The backing field has the same name as the Property
// but all letters must be lowercase.
private int number;
public int Number
{
get { return number; }
set
{
if (value > 0)
number = value;
else
number = 0;
}
}
// In the constructor we set the value of the backing fields
// using the corresponding properties.
public Class1(int number)
{
Number = number;
}
}
The each time you want to set the value of number or get it's value you use the corresponding property:
// Set the value 2 to the number
Number = 2;
// Read the value stored in number and assigned to value.
var value = Number;

Categories