Got NullReferenceException When I use same code but different expression - c#

I'm writing a project about game's character data.
And each character in the data document have four types, Lv1 and LvMAX, and HP, STR, VIT, INT, MEN.
I use top one code at the middle part and got NullReferenceException when I use it to get some data like:
int x = CD.Parameters.Basic.Awaked.Force.Lv1.STR;
Force will be null. But when I use buttom one at the middle part, Force won't be null.
What's the difference between that two?
Code below
public class ParamType
{
public ParamLv Mebius, Force, Aegis, Magius;
string cost;
DataRow[] Datas;
List<int> ToMebius = new List<int>(), ToForce = new List<int>(), ToAegis = new List<int>(), ToMagius = new List<int>(); //HP, HP, STR, STR, VIT, VIT, INT, INT, MEN, MEN
public ParamType(SData Data, bool awaked)
{
if (awaked)
{
Data.CharaID = CharaCOM.AwakedID(Data.CharaID);
}
Datas = DataCOM.Search(Data.CharaID, Data.DTs.Source, Data.TitleP.Start[(int)DataTitle.CharacterParams], Const.COL_CHARACTER_ID, Const.COL_CHARACTER_ID);
cost = DataCOM.Search(Data.DTs.Source, Data.CharaID, Const.COL_COST, 0, Data.TitleP.Start[(int)DataTitle.CharacterParams], Const.COL_CHARACTER_ID_WITH_TYPE);
List<int>[] SArray = { ToMebius, ToForce, ToAegis, ToMagius };
for (int i = 0; i < Datas.Length; i++)
{
SArray[i] = new List<int>();
for (int j = Const.COL_PARAM_MIN; j < Const.COL_PARAM_MIN + Const.COL_PARAM_LENGTH; j++)
{
SArray[i].Add(Convert.ToInt32(Datas[i][j]));
}
}
/*
this will send NullReference Exception
ParamLv[] PLArray = new ParamLv[4];
for (int i = 0; i < SArray.Length; i++)
{
PLArray[i] = new ParamLv(Data, SArray[i]);
}
*/
/*
This won't get exception and I can get correct data I want.
Mebius = new ParamLv(Data, SArray[0]);
Force = new ParamLv(Data, SArray[1]);
Aegis = new ParamLv(Data, SArray[2]);
Magius = new ParamLv(Data, SArray[3]);
*/
}
public class ParamLv
{
public Params Lv1, LvMax;
List<int> ToLv1 = new List<int>(), ToLvMAX = new List<int>(); //HP, STR, VIT, INT, MEN
public ParamLv(SData Data, List<int> ParamsL)
{
for (int i = 0; i < ParamsL.Count; i += Const.COL_PARAM_MIN_MAX_GAP)
{
ToLv1.Add(ParamsL[i]);
ToLvMAX.Add(ParamsL[i + 1]);
}
Lv1 = new Params(Data, ToLv1);
LvMax = new Params(Data, ToLvMAX);
}
public class Params
{
//some method and properties to get or set Parameters.
}
}
Please tell me if something still bad, and this is my first time to ask question here, so If I did something wrong, please tell me. Thanks for #MicroVirus , #Moriarty and #mvikhona told my mistake.

Mebius = new ParamLv(Data, SArray[0]);
Force = new ParamLv(Data, SArray[1]);
Aegis = new ParamLv(Data, SArray[2]);
Magius = new ParamLv(Data, SArray[3]);
This works, because you are assigning reference to new ParamLv to your properties.
But in this case:
ParamLv[] PLArray = { Mebius, Force, Aegis, Magius };
for (int i = 0; i < PLArray.Length; i++)
{
PLArray[i] = new ParamLv(Data, SArray[i]);
}
you aren't filling your array with variables/properties themselves, but you are filling it with references your properties hold, in the end your array will hold reference to 4 new ParamLw, but your property Force will stay null.
Edit:
I'll try to explain it a bit different. Let's say you have this code:
ParamLv[] PLArray = { Force };
At this moment value of PLArray[0] is same as value of Force, but PLArray[0] isn't Force.
The moment you do this:
PLArray[0] = new ParamLv(Data, null);
new ParamLv(Data, null) returns reference to new ParamLv and you assign this to your PLArray[0], but like I said before PLArray[0] isn't Force, so Force will stay unchanged.
If that didn't explain it well, try to look at this piece of code, it does what you are trying to do.
int a = 1;
int[] myArr = { a }; // a = 1, myArr[0] = 1
myArr[0] = 2; // a = 1, myArr[0] = 2
object obj = null;
object[] objArr = { obj }; // obj = null, objArr[0] = null
objArr[0] = new object(); // obj = null, objArr[0] = 'reference to new object'

Related

How to add forloop in If-Else condition in c#?[CODEDOM]

How to execute the following code in Codedom:
if(statement)
{
for(int = 0; i < 10; i++)
{
Console.WriteLine(i);
}
}
I'm familiar with CodeIterationStatement and CodeConditionStatement but don't know how to execute it.
What type of statement or condition you want to put to execute inside loop is depend upon requirement. I guess there should be a condition inside if statement lets understand by example
int a=5;
if(a>1)
{
for(int i=0;i<10;i++)
{
Console.WriteLine("{0}",i);
}
}
This should do the trick
private CodeConditionStatement makeIfStatementWithLoop(CodeExpression conditionExpr, CodeExpression iterationLimit)
{
CodeConditionStatement ifStatement = new CodeConditionStatement();
ifStatement.Condition = conditionExpr;
CodeVariableDeclarationStatement iDeclaration = new CodeVariableDeclarationStatement(new CodeTypeReference(typeof(int)), "i");
CodeVariableReferenceExpression iReference = new CodeVariableReferenceExpression(iDeclaration.Name);
CodeIterationStatement loopStatement = new CodeIterationStatement();
loopStatement.InitStatement = new CodeAssignStatement(iReference, new CodePrimitiveExpression(0));
CodeAssignStatement incrementStatement = new CodeAssignStatement();
incrementStatement.Left = iReference;
incrementStatement.Right = new CodeBinaryOperatorExpression(iReference, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1));
loopStatement.IncrementStatement = incrementStatement;
loopStatement.TestExpression = new CodeBinaryOperatorExpression(iReference, CodeBinaryOperatorType.LessThan, iterationLimit);
CodeVariableReferenceExpression consoleRef = new CodeVariableReferenceExpression("Console");
CodeExpression[] args = new CodeExpression[] { iReference };
CodeMethodInvokeExpression consoleWriteLineStmt = new CodeMethodInvokeExpression(consoleRef, "WriteLine", args);
loopStatement.Statements.Add(consoleWriteLineStmt);
ifStatement.TrueStatements.Add(loopStatement);
return ifStatement;
}

How to pass a Method with parameters to another method

I'm trying to build up a Data Matrix which comprises a list of objects. So here's what I am trying to do:
List<IBasePremium> BasePremiumMatrix = new List<IBasePremium>();
List<ICalcRate> calcRates = new List<ICalcRate>
{
new CalcRate { BasePremiumType = 1, Rate = basePremiumRate.Building, Calc = basePremiumRate.Building },
new CalcRate { BasePremiumType = 2, Rate = basePremiumProduct.Building,Calc = calculator.BasePremium(basePremiumProduct.Building,basePremiumRate.Building) }
// new CalcRate { BasePremiumType = 3, Rate = (decimal)postcodeMultiplier.BuildingsCore ,Calc = calculator.BasePremium(postcodeMultiplier.BuildingsCore, ) },
};
on my line of code that is commented out, as the second parameter I really want to pass the value of 'Calc' from the previous line of code. I've got a number of lines like this where I need to pass the previous 'Calc' value to build the matrix. The above is clearly the wrong approach and thought that I'd be able to write a method that takes the form something like :
public CalcRate Multiplier(Func<string,decimal>, int basePremiumType, decimal rate) {.....}
But I'm fighting witrh passing the method name and it's parameter values.
Create and Action or a Func :
Action customAction = ()=> yourFunctionName(param1, param2);
then pass it to the multiplier.
var calcul = Multiplier(customAction , ....);
How about a for loop?
List<IBasePremium> BasePremiumMatrix = new List<IBasePremium>();
List<ICalcRate> calcRates = new List<ICalcRate>();
for (int i = 1; i < max; i++) {
CalcRate rate = new CalcRate { BasePremiumType = i , Rate = basePremiumRate.Building };
if ( i > 1) {
rate.Calc = calcRates.get(i - 2)
} else {
rate.Calc = calculator.BasePremium(basePremiumProduct.Building,basePremiumRate.Building);
}
calcRates.add(rate);
}

Making var 's in a for-loop

It is hard to explain but I will show an example of what I want in my code:
At the moment I do it this way:
var something1 = new (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet);
var something2 = new (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet);
var something3 = new (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet);
something1.Name = "sheet1";
something2.Name = "sheet2";
something3.Name = "sheet3";
I want to do the making of those var's in a for-loop
This is what I thought it should be:
for (int i=1;i<4;i++)
{
var ("something" +i) = new Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet); // this (of course) doenst work
}
Any ideas on how to do this?
I tried this, but it didn't work:
var something = new (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1 , XlSheetType.xlWorksheet)[4];
you can use a dictionary
var somethigs = new Dictionary<int, xxx.ApplicationClass>();
for (var i = 1; i < 4; i++)
{
somethigs[i] = new xxx.ApplicationClass();
}
//access them like this
somethigs[1].Name = "sheet1";
somethigs[2].Name = "sheet2";
or use an array like this
var somethigs = new xxx.ApplicationClass[4];
for (var i = 0; i < 4; i++)
{
somethigs[i] = new xxx.ApplicationClass();
}
somethigs[0].Name = "sheet1";
somethigs[1].Name = "sheet2";
keep in mind that arrays have zero based indexes.
If you know for sure, the amount of instances you will need, creating an array or list of class instances will do what you are after.
If you want something more sophisticated, you could also create a dictionary in which you provide names to each of your class instances, this could provide you with an access by name sort of thing mechanism.
Dictionary<string, ApplicationClass> dictionary = new Dictionary<string, ApplicationClass>();
for(int i = 0; i < 4; i++) {
dictionary.Add("something" + i, new xxx.ApplicationClass());
}
var myApplicationClass = dictionary["something1"];
You should use an array. In your particular case,
var something = new xxx.ApplicationClass[4];
for (int i = 0; i < 3; i++)
{
something[i] = new (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet);
something[i].Name = "sheet" + (i + 1).ToString();
}
You should probably look for more information about what arrays an how they work. See for example https://msdn.microsoft.com/en-us/library/aa288453%28v=vs.71%29.aspx

Correct way to initialize object in array of objects so that i don't get null pointer references?

I am receiving a null pointer exception, and I narrowed it down to this small block of code. I think it is because when I set teamStats[iterator].median = Statistics.median that it can't because it isn't initialized yet. Though I don't know the proper way to initialize an array of objects or the memory ramifications that this code will cause.
Below is the majority of the code i am dealing with besides the class describing TeamStat, but I've used all of its members below and they are public double.
TeamStat[] teamStats = new TeamStat[DistCount+1];
int iterator = 0;
foreach (int i in TeamIDlist)
{
var p = userList.Where(x => x.TeamId.Equals(i)).Select(y => (double)y.BS).ToArray();
var statistics = new DescriptiveStatistics(p);
teamStats[iterator].median = Statistics.Median(p);
teamStats[iterator].largestElement = statistics.Maximum;
teamStats[iterator].smallestElement = statistics.Minimum;
teamStats[iterator].mean = statistics.Mean;
teamStats[iterator].variance = statistics.Variance;
teamStats[iterator].stdDev = statistics.StandardDeviation;
iterator++;
}
Update
Is this the correct way to do this:
TeamStat[] teamStats = new TeamStat[DistCount];
int iterator = 0;
foreach (int i in TeamIDlist)
{
//Added these two lines
TeamStat temp = new TeamStat();
teamStats[iterator] = temp;
var p = userList.Where(x => x.TeamId.Equals(i)).Select(y => (double)y.BS).ToArray();
var statistics = new DescriptiveStatistics(p);
teamStats[iterator].median = Statistics.Median(p);
teamStats[iterator].largestElement = statistics.Maximum;
teamStats[iterator].smallestElement = statistics.Minimum;
teamStats[iterator].mean = statistics.Mean;
teamStats[iterator].variance = statistics.Variance;
teamStats[iterator].stdDev = statistics.StandardDeviation;
iterator++;
}
Here
TeamStat[] teamStats = new TeamStat[DistCount+1];
you initialize the array. At this moment, the array contains DistCount + 1 null entries.
If you want the array to contain DistCount + 1 new TeamStat entries, you need to initialize them in a loop:
TeamStat[] teamStats = new TeamStat[DistCount+1];
for (var i = 0; i < DistCount + 1; i++)
teamStats[i] = new TeamStat();
Your code has 2 issues
1) Each object in Array needs to be initialized before accseing its properties
teamStats[iterator] = new TeamStat();
2) You need to make sure you initizliaed array with same/more capacity as you are trying to assign values to.(TeamIDlist < DistCount+1), otheriwse it will throw index out of range exception.

To create a list with multiple list inside it

Below is my main list
var serie_line = new { name = series_name, data = new List<object>() };
here I add items in data as follows,
serie_line.data.Add(child_object_name);
serie_line.data.Add(period_final_value );
I then add this var serie_line to another list series as follows,
List<object> series = new List<object>();
series.Add(serie_line);
finally ,I serialize this series into JSON as below,
var obj4 = new { legend = legend, title,chart, series};
JSON_File_Returned = jSearializer.Serialize(obj4);
whereas
System.Web.Script.Serialization.JavaScriptSerializer jSearializer = new System.Web.Script.Serialization.JavaScriptSerializer();
Now Output I am getting is as follows,
{
"legend":{"enabled":"true"},
"title":{"text":"Financial"},
"chart":{"type":"pie"},
"series":[
{"name":"Actual","data":["Market Share",20.00]},
{"name":"Actual","data":["Sales Growth",30.00]},
{"name":"Actual","data":["Operating Profit",40.00]},
{"name":"Actual","data":["Gross Margin %",10.00]}
]
}
But my required output is as follows,
{
"legend":{"enabled":"true"},
"title":{"text":"Financial"},
"chart":{"type":"pie"},
"series":[
{"name":"Actual","data":[["Market Share",20.00],["Sales Growth",30.00],["Operating Profit",40.00],["Gross Margin %",10.00]]}
]
}
So..That I can plot pie chart in highchart using this JSON output...I have tried for everything like using dictionary,making different class and then using it's object and so on...but can't make it out....
Below is my entire code...if in case I am messing with any loop and I don't recognize it but any one might notice it..please check the below code for the same..
var serie_line = new { name = series_name, data = new List<object>() };
for (int k = 0; k <= read_Series_Splitted_Name.Length; k++) //for loop for passing chart type in series
{
for (int i = 0; i < id_series_before_offset.Count; i++) //for loop for counting series ID
{
var xmlAttributeCollection = id_series_before_offset[i].Attributes;
if (xmlAttributeCollection != null)
{
var seriesid = xmlAttributeCollection["id"];
xmlActions_id[i] = seriesid.Value;
resulted_series_id = seriesid.Value;
series_name = Client.GetAttributeAsString(sessionId, resulted_series_id, "name", "");
new_series_name = series_name;
series_Atribute = Client.GetAttributeAsString(sessionId, resulted_series_id, "symbol", "");
if (read_Series_Splitted_Name_store == series_Atribute)
{
serie_line = new { name = series_name, data = new List<object>() };
}
k++;
// Forloop for PeriodId and It's Value
var value = Read_XML_Before_Offset.SelectNodes("//measure.values/series[" + (i + 1) + "]/value");
var xmlActions = new string[value.Count];// for periodname
var xmlActionsone = new string[value.Count]; // for period value
for (int j = 0; j < value.Count; j++)
{
var xmlAttributeCollection_for_period = value[j].Attributes;
if (xmlAttributeCollection_for_period != null)
{
if (i == 0 && a == 0)
{
var periodid = xmlAttributeCollection_for_period["periodid"];
xmlActions[j] = periodid.Value;
period_final_id = periodid.Value;
period_name = Client.GetAttributeAsString(sessionId, periodid.Value, "name", "");
period_Name.Add(period_name);
}
try
{
var action = xmlAttributeCollection_for_period["value"]; // xmlActionsone[j] = action.Value;
period_final_value = float.Parse(action.Value);
// serie_line.data.Add(period_final_value);
serie_line.data.Add(child_object_name);
serie_line.data.Add(period_final_value );
}
catch (Exception ex1)
{
serie_line.data.Add("");
serie_line.data.Add( null );
}
}
}
}
}
}
series.Add(serie_line);
Your C# code should look something like this all stripped down:
var serie_line = new { name = "Actual", data = new List<object>() };
serie_line.data.Add(new List<object>() {"Market Share", 20.0});
serie_line.data.Add(new List<object>() {"Sales Growth", 30.0});
serie_line.data.Add(new List<object>() {"Operting Profit", 40.0});
serie_line.data.Add(new List<object>() {"Gross Margin %", 10.0});
jSearializer.Serialize(serie_line);
Which produces:
{"name":"Actual","data":[["Market Share",20],["Sales Growth",30],["Operting Profit",40],["Gross Margin %",10]]}
I'm not following the bottom part of the code (how you create child_object_name and period_final_value, but I think you want:
serie_line.data.Add(new List<object>() {child_object_name, period_final_value });
Instead of:
serie_line.data.Add(child_object_name);
serie_line.data.Add(period_final_value );

Categories