NUnit Is.EqualTo treats different refenceres as equal - c#

I'm copying an array like this:
var arrayOfMyTypes = new IMyType[1, 2]; //IMyType is an interface
arrayOfMyTypes[0, 0] = new MyType(); // that MyType implements
arrayOfMyTypes[0, 1] = new MyType();
var xRange = arrayOfMyTypes.GetLength(0);
var yRange = arrayOfMyTypes.GetLength(1);
var copy = new IMyType[xRange, yRange];
for (var xIdx = 0; xIdx < xRange; xIdx++)
{
for (var yIdx = 0; yIdx < yRange; yIdx++)
{
copy[xIdx, yIdx] = arrayOfMyTypes[xIdx, yIdx];
}
}
Assert.That(copy, Is.EqualTo(arrayOfMyTypes)); // true
Assert.That(copy, Is.Not.EqualTo(arrayOfMyTypes)); // false
To be clear, I want the elements be the same and the array a different one. So why are arrayOfMyTypes and copy considered equal by Nunit?

If you want to compare references rather than values, use Is.SameAs:
Assert.That(copy, Is.SameAs(arrayOfMyTypes)); // false

Related

How can I access multi-element List data stored in a public class?

My first question on SO:
I created this public class, so that I can store three elements in a list:
public class myMultiElementList
{
public string Role {get;set;}
public string Country {get;set;}
public int Commonality {get;set;}
}
In my main class, I then created a new list using this process:
var EmployeeRolesCountry = new List<myMultiElementList>();
var rc1 = new myMultiElementList();
rc1.Role = token.Trim();
rc1.Country = country.Trim();
rc1.Commonality = 1;
EmployeeRolesCountry.Add(rc1);
I've added data to EmployeeRolesCountry and have validated that has 472 lines. However, when I try to retrieve it as below, my ForEach loop only retrieves the final line added to the list, 472 times...
foreach (myMultiElementList tmpClass in EmployeeRolesCountry)
{
string d1Value = tmpClass.Role;
Console.WriteLine(d1Value);
string d2Value = tmpClass.Role;
Console.WriteLine(d2Value);
int d3Value = tmpClass.Commonality;
Console.WriteLine(d3Value);
}
This was the most promising of the potential solutions I found on here, so any pointers greatly appreciated.
EDIT: adding data to EmployeeRolesCountry
/*
Before this starts, data is taken in via a csvReader function and parsed
All of the process below is concerned with two fields in the csv
One is simply the Country. No processing necessary
The other is bio, and this itself needs to be parsed and cleansed several times to take roles out
To keep things making sense, I've taken much of the cleansing out
*/
private void File_upload_Click(object sender, EventArgs e)
{
int pos = 0;
var EmployeeRolesCountry = new List<myMultiElementList>();
var rc1 = new myMultiElementList();
int a = 0;
delimiter = ".";
string token;
foreach (var line in records.Take(100))
{
var fields = line.ToList();
string bio = fields[5];
string country = fields[4];
int role_count = Regex.Matches(bio, delimiter).Count;
a = bio.Length;
for (var i = 0; i < role_count; i++)
{
//here I take first role, by parsing on delimiter, then push back EmployeeRolesCountry with result
pos = bio.IndexOf('.');
if (pos != -1)
{
token = bio.Substring(0, pos);
string original_token = token;
rc1.Role = token.Trim();
rc1.Country = country.Trim();
rc1.Commonality = 1;
EmployeeRolesCountry.Add(rc1);
a = original_token.Length;
bio = bio.Remove(0, a + 1);
}
}
}
}
EDIT:
When grouped by multiple properties, this is how we iterate through the grouped items:
var employeesGroupedByRolwAndCountry = EmployeeRolesCountry.GroupBy(x => new { x.Role, x.Country });
employeesGroupedByRolwAndCountry.ToList().ForEach
(
(countryAndRole) =>
{
Console.WriteLine("Group {0}/{1}", countryAndRole.Key.Country, countryAndRole.Key.Role);
countryAndRole.ToList().ForEach
(
(multiElement) => Console.WriteLine(" : {0}", multiElement.Commonality)
);
}
);
__ ORIGINAL POST __
You are instantiating rc1 only once (outside the loop) and add the same instance to the list.
Please make sure that you do
var rc1 = new myMultiElementList();
inside the loop where you are adding the elements, and not outside.
All references are the same in your case:
var obj = new myObj();
for(i = 0; i < 5; i++)
{
obj.Prop1 = "Prop" + i;
list.Add(obj);
}
now the list has 5 elements, all pointing to the obj (the same instance, the same object in memory), and when you do
obj.Prop1 = "Prop" + 5
you update the same memory address, and all the pointers in the list points to the same instance so, you are not getting 472 copies of the LAST item, but getting the same instance 472 times.
The solution is simple. Create a new instance every time you add to your list:
for(i = 0; i < 5; i++)
{
var obj = new myObj();
obj.Prop1 = "Prop" + i;
list.Add(obj);
}
Hope this helps.

How to set a dynamic objects array property with a list of a different dynamic object

I'm passing in 2 dynamic objects into my method. 'injuredParty' has a property called dependents that's an array of dependents that I want to fill with the second dynamic object 'dependent'
Is this possible?
public static dynamic MapTrustOnline(DetailedDto detailed, dynamic injuredParty, dynamic dependent) {
injuredParty.dependents = new dependent[4];
for(int i = 0; i <= detailed.dependents.length; i++) {
var dynDependent = new dependent();
dynDependent.property1 = detailed.dependents[i].property1;
dynDependent.property2 = detailed.dependents[i].property2;
injuredParty.dependents[i] = dynDependent;
}
}
I solved it by passing in the dependent object in the class and then doing this below.
var genDependents = detailedClaim.Matter.MatterData.GeneralDependentDto;
inj.dependents = new T[genDependents.Count];
var i = 0;
foreach (var dep in genDependents) {
T myObj = new T();
var birthDateProp = myObj.GetType().GetProperty("birthdate");
birthDateProp.SetValue(myObj, (DateTime)dep.BirthDate, null);
inj.dependents[i] = myObj;
i++;
}

Got NullReferenceException When I use same code but different expression

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'

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.

Categories