Wrong value displayed - c#

I'm learning C#, I have this code :
namespace foo
{
public class Personnes
{
string[] m_Noms;
int m_NbElt;
int m_Max;
public Personnes(int Max)
{
m_Max = Max;
m_NbElt = 0;
m_Noms = new string[Max];
}
public int this[string Nom]
{
get { return Array.IndexOf(m_Noms, Nom); }
}
public string this[int i]
{
get { return m_Noms[i]; }
set { m_Noms[i] = value;m_NbElt++; }
}
}
class Prog
{
static void Main(string[] args)
{
Personnes Tableau = new Personnes(4);
Tableau[0] = "Anna";
Tableau[1] = "Ingrid";
Tableau[2] = "Maria";
Tableau[3] = "Ulrika";
Console.WriteLine(Tableau[1]);
Console.WriteLine(Tableau["Maria"]);
Console.WriteLine(Tableau[10]);
Console.WriteLine(Tableau["Toto"]);
}
}
}
I've been told that Console.WriteLine(Tableau[10]); should display null and the next line -1 but it doesn't, instead I have an error IndexOutOfRange, why ?

It is displaying IndexOutOfRangeException because you have set Tableau to have only 4 strings and any array retrieval beyond the index range[0 to 3] will result in this.
public string this[int i]
{
get { return m_Noms[i]; } <-- displays error if outside the range
set { m_Noms[i] = value;m_NbElt++; }
}
If you have to display null, then you need to add conditions in the indexer logic to check for the index value and if it is out of range return null

See you have initialized your array Tableau with just 4 Personnes(4). And you are trying to get what is at Tableau[10], so your are correctly getting IndexOutOfRange exception. The index that you are seeking is out of the range specified.

I've been told that Console.WriteLine(Tableau[10]); should display null and the next line -1 but it doesn't, instead I have an error IndexOutOfRange, why ?
Because whoever told you that was wrong. Accessing an array with an index that does not exist should throw an exception.

Related

My IF property is being ignored in my class when i use it

public class Irritante : Child
{
/*Fields*/
private int ir_numeroBirras;
private double ir_mediaBirras;
/*Properties*/
public int NumeroBirras
{
get { return ir_numeroBirras; }
set { if (value > 0) ir_numeroBirras = value; }
}
public double MediaBirras
{
get { return ir_mediaBirras; }
set { ir_mediaBirras = value; }
}
//Constructor
public Irritante(string nome, int idade, int numBirras, double mediaDasBirras) : base(nome, idade)
{
NumeroBirras = numBirras;
ir_mediaBirras = mediaDasBirras;
}
When i try to use the contructor Irritante with the property NumeroBirras it is ignoring the if(value>0)
This means i can still add a 0 to this field with client code, which i should not be able to, any tips? i cant find it anywhere
The default value of ir_numeroBirras is 0. You can't put a 0 using the property. But if you test using a 0 as parameter value, you are being fooled by the default value.
If you're talking about you shouldn't put a 0 in the parameter of Irritante ctor, that's quite different
public Irritante(string name, int idade, int numBirras, double mediaDasBirras) : base(nome, idade)
{
if(numBirras < 1) throw new ArgumentOutOfRangeException(nameof(numBirras), "Hey, you can't drink 0 beers");
ir_numeroBirras = numBirras;
ir_mediaBirras = mediaDasBirras;
}

If int value equal to x replace with a string

I am storing a int in schadstoffklasse so when calling the Car object like so (last int in brackets) :
PKW Kaefer = new PKW("VW", "Käfer", "K-GS-01", 1965, 9999, 1000, 30, 1);
I can either say 0, 1, 2.
Now when i write this Console.WriteLine(Kaefer.Schadstoffklasse)
to the console it obiously outputs 1 in this case.
I do want it to not say 1 i want for example....
0 = foo
1 = bar
2 = foobar
So it outputs to the console a string.
Here is what i have tried, which does not work.
private int schadstoffklasse;
public int Schadstoffklasse
{
get
{
return schadstoffklasse;
}
set
{
if (value == 0)
{
string foo = value.ToString();
foo = "BLABLALBA";
}
schadstoffklasse = value;
}
}
Thank you for having patience with a beginner
You can't have a property return mixed types. Your property of Schadstoffklasse is an int, therefore it can only ever return an int never a string.
There are a variety of different ways to accomplish this though, but without knowing more of how you are using this it'd be impossible to say which one you should do. I'd recommend either another property that has no setter and the getter looks at the other property, reads it's value and returns the string that you want or a method that does the same.
To expand on my suggestion:
public enum SchadstofklasseStrings
{
foo = 0,
bar = 1,
foobar = 2
}
public int Schadstoffklasse { get; set; }
public string SchadstoffklasseToString {
{
get
{
var stringValue = (SchadstofklasseStrings) Schadstoffklasse;
return stringValue.ToString();
}
}
Also, sorry for mutilating the German.
You can't change the type of a variable from int to string .
in this case i would create an array
["foo","bar","foobar"]
and use value of schadstoffklasse as an index
Console.WriteLine(Kaefer.myArray[Schadstoffklasse]);
Try this
private int schadstoffklasse;
public object Schadstoffklasse
{
get
{
if(this.schadstoffklasse==0)
return "foo";
if(this.schadstoffklasse==1)
return "bar";
if(this.schadstoffklasse==2)
return "foobar";
return "N/A";
}
set
{
this.schadstoffklasse=(int)value;
}
}
Note: The explain from user #gilliduck is useful. Consider this just
as a situational workaround.
I find enum helpful in situations like this since it is a collection of named integers. This is one example of how I might handle it.
void Main()
{
var Kaefer = new PKW("VW", "Käfer", "K-GS-01", 1965, 9999, 1000, 30, Schadstoffklassen.Bar);
Console.WriteLine(Enum.GetName(typeof(Schadstoffklassen), Kaefer.Schadstoffklasse));
// Output: Bar
}
public class PKW
{
private Schadstoffklassen schadstoffklasse;
public PKW(string v1, string v2, string v3, int v4, int v5, int v6, int v7, Schadstoffklassen _schadstoffklasse) {
schadstoffklasse = _schadstoffklasse;
}
public Schadstoffklassen Schadstoffklasse
{
get { return schadstoffklasse; }
set { schadstoffklasse = value; }
}
}
public enum Schadstoffklassen {
Foo = 0,
Bar = 1,
FooBar = 2
}

Error on Value of Dictionary and List Declaration due to negative sign value C#

What does this error mean on my code i see while debugging some output are negative which triggers this error while also in the other hand i saw a Dictionary with two parameters int and decimal but then to be stored to a list of int declare could this be also triggering the crash? what are the possible remedy for this crash error?
Picture of the Error Message Crash
function is declared on a class called PriceTierModel
private Dictionary<int, decimal> _unitPrices = new Dictionary<int, decimal>(); // key == TurnTime
public void AddPrice(int turnTimeValue, decimal price)
{
_unitPrices[turnTimeValue] = price;
}
public List<int> TurnTimes
{
get
{
List<int> turnTimes = _unitPrices.Keys.ToList();
turnTimes.Sort();
return turnTimes;
}
}
which is used here in this other class
public override string Error
{
get
{
PriceTierModel priceTier = GetPriceTier();
try
{
if (priceTier != null && _desiredTurnTime < Math.Abs(priceTier.TurnTimes[0]))
{
return String.Format(CadFramework.Rm.GetString("TurnTimeTooSoon"), priceTier.TurnTimes[0]);
}
}
catch (Exception ei) { return String.Format(CadFramework.Rm.GetString("TurnTimeTooSoon"), Math.Abs(priceTier.TurnTimes[0])); }
return "";
}
}
Added Code for Showing implementation use of the function.
foreach (XElement tier in priceTiers)
{
// possible that the tier element is invalid
//<price_tier>
// <turn_time></turn_time>
// <unit_price>N/A</unit_price>
// <turn_time_days>None days</turn_time_days>
//</price_tier>
int turnTime;
// ReSharper disable once PossibleNullReferenceException
if (int.TryParse(tier.Element("turn_time").Value, out turnTime))
{
decimal unitPrice = decimal.Parse(!string.IsNullOrEmpty(tier.Element("unit_price").Value) ? tier.Element("unit_price").Value : "0", CultureInfo.InvariantCulture);
priceTier.AddPrice(turnTime, unitPrice); <-- Here
}
}
This error means, that the line:
try
{
/* --> */ if (priceTier != null && _desiredTurnTime < Math.Abs(priceTier.TurnTimes[0]))
{
return String.Format(CadFramework.Rm.GetString("TurnTimeTooSoon"), priceTier.TurnTimes[0]);
}
or the line:
public void AddPrice(int turnTimeValue, decimal price)
{
/* --> */ _unitPrices[turnTimeValue] = price;
}
is entering or accessing (thanks to commentator) an item that is not existing in one of the both list.
From MSDN (IndexOutOfRangeException):
The exception that is thrown when an attempt is made to access an
element of an array or collection with an index that is outside its
bounds.

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.

Creating a Session Helper Class that uses an array object C#

I am using a session helper class to track more than several variable. So far I have 30 that are needed from page to page, not all at once of course. I need to convert some of the values from single to array. The Session helper class I use is as follows. For brevity I have shown only two session variables we use for tracking tab index for two accordions.
using System;
using System.Globalization;
using System.Linq;
using System.Web;
public class SessionHelper
{
//Session variable constants
public const string AccordionTop = "#tabTop";
public const string AccordionBot = "#tabBot";
public static T Read<T>(string variable)
{
object value = HttpContext.Current.Session[variable];
if (value == null)
return default(T);
else
return ((T)value);
}
public static void Write(string variable, object value)
{
HttpContext.Current.Session[variable] = value;
}
public static int TabTop
{
get
{
return Read<int>(AccordionTop);
}
set
{
Write(AccordionTop, value);
}
}
public static int TabBot
{
get
{
return Read<int>(AccordionBot);
}
set
{
Write(AccordionBot, value);
}
}
}
So on each page I can work with variables easily as follows:
To Write:
SessionHelper.TabTop = 1; or SessionHelper.TabBot = 3
To Read:
If (SessionHelper.TabTop……….)
This all works fine. I now want to extend this to array values held in session. The array contains int, string and date time value.
For the array session object I have tried adding:
public class SessionHelper
{
public const string CompInfo = "CompAccInfo";
public static T ReadArray<T>(string variable)
{
object[] result = HttpContext.Current.Session[variable] as object[];
if (result == null)
{
return default(T);
//result = new object[30];
}
else
return ((T)(object)result);
}
public static void WriteArray(string variable, object[] value)
{
HttpContext.Current.Session[variable] = value;
}
public static object[] CompDetails
{
get
{
return ReadArray<object[]>(CompInfo);
}
set
{
WriteArray(CompInfo, value);
}
}
}
But then I get an “Object reference not set to…… error when I try to do this:
public void EGetCompanyInformation(MasterPage myMaster, int entityCode)
{
int prevEntity = 0;Using (sqlconnetiooo
.....
//I get values here this works fine
//Then:
sqlr = cmd.ExecuteReader();
sqlr.Read();
if (sqlr.HasRows)
{
//Calculate accounting period adjustment.
yearEndDiff = 12 - Convert.ToInt32(sqlr.GetDateTime(5).Month);
//Company Code.
SessionHelper.CompDetails[0] = sqlr.GetInt32(0);
//Company Name.
SessionHelper.CompDetails[1] = sqlr.GetString(1);
//Currency Unit.
SessionHelper.CompDetails[2] = sqlr.GetString(2);
//Base Currency Code.
SessionHelper.CompDetails[3] = sqlr.GetString(3);
//Reporting Currency Code.
SessionHelper.CompDetails[4] = sqlr.GetString(4);
//Company Year End.
SessionHelper.CompDetails[5] = yearEndDiff;
//Country Code.
SessionHelper.CompDetails[6] = sqlr.GetString(6);
//Country Name.
SessionHelper.CompDetails[7] = sqlr.GetString(7);
//Base Currency Name.
SessionHelper.CompDetails[8] = sqlr.GetString(8);
//Report Currency Name.
SessionHelper.CompDetails[9] = sqlr.GetString(9);
//ClientID.
SessionHelper.CompDetails[10] = sqlr.GetInt32(10);
Other code here
}
}
It seems any SessionHelper.CompDetails[i] does not work : Error Object reference not set to an instance of an object.
What will happen if ReadArray will return default(T)? It will return null. Than access to any object by index inside the array will cause the exception you face.
It is not quite obvious what your code is intended to do.
SessionHelper.CompDetails[0] = sqlr.GetInt32(0);
What do you want here? CompDetails itself should return an array. But you are trying to rewrite it immediately by some values.
If you want to access the CompDetails and rewrite it's objects than you have to instantiate it by
int n = 10;
SessionHelper.CompDetails = new CompDetails[n];
default(object[]) will always throw null. because the array of object is reference type and default value of any reference type is null. So accessing null value will get you Object reference not set to an instance of object.
You can change your old implementation like below:
public static T Read<T>(string variable, int arraySize=10)
{
object value = HttpContext.Current.Session[variable];
if(typeof(T).IsArray && value == null)
{
//array requires size I personally prefer to have
//differnt read method for array.
return ((T)Activator.CreateInstance(typeof(T),arraySize));
}
if(!typeof(T).IsValueType && value == null)
{
//if it is not value type you can return new instance.
return ((T)Activator.CreateInstance(typeof(T)));
}
else if (value == null)
return default(T);
else
return ((T)value);
}
And access SessionHelper as below:
var sessionarray = SessionHelper.Read<object[]>("myarray",15);
....
// then use that sessionarray here.
....
You have to instantiate the CompDetails array before you start assigning values to it.
if (sqlr.HasRows)
{
//Calculate accounting period adjustment.
yearEndDiff = 12 - Convert.ToInt32(sqlr.GetDateTime(5).Month);
// Instantiate array
SessionHelper.CompDetails = new object[11];
//Company Code.
SessionHelper.CompDetails[0] = sqlr.GetInt32(0);
// etc

Categories